UNPKG

@ayonli/jsext

Version:

A JavaScript extension package for building strong and modern applications.

238 lines (234 loc) 8.32 kB
'use strict'; var array = require('../array.js'); require('../error.js'); var fs_errors = require('./errors.js'); var filetype = require('../filetype.js'); var object = require('../object.js'); var path = require('../path.js'); var path_util = require('../path/util.js'); var error_Exception = require('../error/Exception.js'); var error_common = require('../error/common.js'); function ensureFsTarget(path$1) { if (path$1 instanceof URL) { if (path$1.protocol !== "file:") { throw new TypeError("Only file URLs are supported"); } else { return path.toFsPath(path$1.href); } } else if (typeof path$1 === "string" && path_util.isFileUrl(path$1)) { return path.toFsPath(path$1); } else { return path$1; } } function getErrorName(err) { if (err.constructor === Error) { return err.constructor.name; } else { return err.name; } } /** * Wraps a raw file system error to a predefined error by this module. * * @param type Used for `FileSystemHandle` operations. */ function wrapFsError(err, type = undefined) { if (err instanceof Error && !(err instanceof error_Exception.default) && !(err instanceof TypeError)) { const errName = getErrorName(err); const errCode = err.code; if (errName === "NotFoundError" || errName === "NotFound" || errCode === "ENOENT" || errCode === "ENOTFOUND") { return new error_common.NotFoundError(err.message, { cause: err }); } else if (errName === "NotAllowedError" || errName === "PermissionDenied" || errName === "InvalidStateError" || errName === "SecurityError" || errName === "EACCES" || errCode === "EPERM" || errCode === "ERR_ACCESS_DENIED") { return new error_common.NotAllowedError(err.message, { cause: err }); } else if (errName === "AlreadyExists" || errCode === "EEXIST" || errCode === "ERR_FS_CP_EEXIST") { return new error_common.AlreadyExistsError(err.message, { cause: err }); } else if ((errName === "TypeMismatchError" && type === "file") || errName === "IsADirectory" || errCode === "EISDIR" || errCode === "ERR_FS_EISDIR") { return new fs_errors.IsDirectoryError(err.message, { cause: err }); } else if ((errName === "TypeMismatchError" && type === "directory") || errName === "NotADirectory" || errCode === "ENOTDIR") { return new fs_errors.NotDirectoryError(err.message, { cause: err }); } else if (errName === "InvalidModificationError" || errName === "NotSupported" || errCode === "ENOTEMPTY" || errCode === "ERR_FS_CP_EINVAL" || errCode === "ERR_FS_CP_FIFO_PIPE" || errCode === "ERR_FS_CP_DIR_TO_NON_DIR" || errCode === "ERR_FS_CP_NON_DIR_TO_DIR" || errCode === "ERR_FS_CP_SOCKET" || errCode === "ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY" || errCode === "ERR_FS_CP_UNKNOWN" || errCode === "ERR_FS_INVALID_SYMLINK_TYPE") { return new fs_errors.InvalidOperationError(err.message, { cause: err }); } else if (errName === "NoModificationAllowedError" || errName === "Busy" || errName === "TimedOut" || errCode === "ERR_DIR_CONCURRENT_OPERATION") { return new fs_errors.BusyError(errName, { cause: err }); } else if (errName === "Interrupted" || errCode === "ERR_DIR_CLOSED") { return new fs_errors.InterruptedError(err.message, { cause: err }); } else if (errName === "QuotaExceededError" || errCode === "ERR_FS_FILE_TOO_LARGE") { return new fs_errors.FileTooLargeError(err.message, { cause: err }); } else if (errName === "FilesystemLoop") { return new fs_errors.FilesystemLoopError(err.message, { cause: err }); } else { return err; } } else if (err instanceof Error) { return err; } else if (typeof err === "string") { return new error_Exception.default(err, { code: 500, cause: err }); } else { return new error_Exception.default("Unknown error", { code: 500, cause: err }); } } /** * Wraps a raw file system operation so that when any error occurs, the error is * wrapped to a predefined error by this module. * * @param type Only used for `FileSystemHandle` operations. */ function rawOp(op, type = undefined) { return op.catch((err) => { throw wrapFsError(err, type); }); } function fixDirEntry(entry) { // for backward compatibility Object.defineProperty(entry, "path", { get() { return entry.relativePath; }, }); return entry; } function fixFileType(file) { var _a; if (!file.type) { const ext = path.extname(file.name); if (ext) { Object.defineProperty(file, "type", { value: (_a = filetype.getMIME(ext)) !== null && _a !== void 0 ? _a : "", writable: false, configurable: true, }); } } return file; } /** * @param addPathProp `DirEntry.prop` is deprecated, this option is for backward * compatibility. */ function makeTree(dir, entries, addPathProp = false) { const list = entries.map(entry => ({ ...entry, paths: path_util.split(entry.relativePath), })); const nodes = (function walk(list, store) { // Order the entries first by kind, then by names alphabetically. list = [ ...array.orderBy(list.filter(e => e.kind === "directory"), e => e.name, "asc"), ...array.orderBy(list.filter(e => e.kind === "file"), e => e.name, "asc"), ]; const nodes = []; for (const entry of list) { if (entry.kind === "directory") { const paths = entry.paths; const childEntries = store.filter(e => array.startsWith(e.paths, paths)); const directChildren = childEntries .filter(e => e.paths.length === paths.length + 1); if (directChildren.length) { const indirectChildren = childEntries .filter(e => !directChildren.includes(e)); const _entry = { ...object.omit(entry, ["paths"]), children: walk(directChildren, indirectChildren), }; addPathProp && fixDirEntry(_entry); nodes.push(_entry); } else { let _entry = { ...object.omit(entry, ["paths"]), children: [], }; addPathProp && fixDirEntry(_entry); nodes.push(_entry); } } else { const _entry = { ...object.omit(entry, ["paths"]), }; addPathProp && fixDirEntry(_entry); nodes.push(_entry); } } return nodes; })(list.filter(entry => entry.paths.length === 1), list.filter(entry => entry.paths.length > 1)); let rootName; if (typeof dir === "object") { rootName = dir.name || "(root)"; } else if (dir) { rootName = path.basename(dir); if (!rootName || rootName === ".") { rootName = "(root)"; } } else { rootName = "(root)"; } const rooEntry = { name: rootName, kind: "directory", relativePath: "", children: nodes, }; if (typeof dir === "object") { rooEntry.handle = dir; } addPathProp && fixDirEntry(rooEntry); return rooEntry; } exports.ensureFsTarget = ensureFsTarget; exports.fixDirEntry = fixDirEntry; exports.fixFileType = fixFileType; exports.makeTree = makeTree; exports.rawOp = rawOp; exports.wrapFsError = wrapFsError; //# sourceMappingURL=util.js.map