@wener/common 2.0.3 → 2.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/ai/qwen3vl/utils.js.map +1 -1
- package/lib/cn/ChineseResidentIdNo.js +1 -1
- package/lib/cn/ChineseResidentIdNo.js.map +1 -1
- package/lib/cn/Mod11.js +1 -1
- package/lib/cn/Mod11.js.map +1 -1
- package/lib/consola/formatLogObject.js +5 -5
- package/lib/consola/formatLogObject.js.map +1 -1
- package/lib/data/maybeNumber.js +1 -1
- package/lib/data/maybeNumber.js.map +1 -1
- package/lib/data/types.d.js.map +1 -1
- package/lib/dayjs/formatDuration.js.map +1 -1
- package/lib/dayjs/resolveRelativeTime.js +9 -80
- package/lib/dayjs/resolveRelativeTime.js.map +1 -1
- package/lib/drain3/Drain.js +356 -0
- package/lib/drain3/Drain.js.map +1 -0
- package/lib/drain3/LogCluster.js +38 -0
- package/lib/drain3/LogCluster.js.map +1 -0
- package/lib/drain3/Node.js +39 -0
- package/lib/drain3/Node.js.map +1 -0
- package/lib/drain3/TemplateMiner.js +204 -0
- package/lib/drain3/TemplateMiner.js.map +1 -0
- package/lib/drain3/index.js +31 -0
- package/lib/drain3/index.js.map +1 -0
- package/lib/drain3/persistence/FilePersistence.js +24 -0
- package/lib/drain3/persistence/FilePersistence.js.map +1 -0
- package/lib/drain3/persistence/MemoryPersistence.js +18 -0
- package/lib/drain3/persistence/MemoryPersistence.js.map +1 -0
- package/lib/drain3/persistence/PersistenceHandler.js +5 -0
- package/lib/drain3/persistence/PersistenceHandler.js.map +1 -0
- package/lib/drain3/types.js +7 -0
- package/lib/drain3/types.js.map +1 -0
- package/lib/fs/IFileSystem.d.js.map +1 -1
- package/lib/fs/createBrowserFileSystem.js +4 -2
- package/lib/fs/createBrowserFileSystem.js.map +1 -1
- package/lib/fs/createMemoryFileSystem.js +7 -6
- package/lib/fs/createMemoryFileSystem.js.map +1 -1
- package/lib/fs/createSandboxFileSystem.js.map +1 -1
- package/lib/fs/createWebDavFileSystem.js +22 -5
- package/lib/fs/createWebDavFileSystem.js.map +1 -1
- package/lib/fs/createWebFileSystem.js +225 -0
- package/lib/fs/createWebFileSystem.js.map +1 -0
- package/lib/fs/findMimeType.js +1 -1
- package/lib/fs/findMimeType.js.map +1 -1
- package/lib/fs/index.js +1 -1
- package/lib/fs/index.js.map +1 -1
- package/lib/fs/minio/createMinioFileSystem.js +974 -0
- package/lib/fs/minio/createMinioFileSystem.js.map +1 -0
- package/lib/fs/minio/index.js +2 -0
- package/lib/fs/minio/index.js.map +1 -0
- package/lib/fs/orpc/createContractClientFileSystem.js +3 -3
- package/lib/fs/orpc/createContractClientFileSystem.js.map +1 -1
- package/lib/fs/orpc/server/createFileSystemContractImpl.js.map +1 -1
- package/lib/fs/s3/createS3MiniFileSystem.js +116 -68
- package/lib/fs/s3/createS3MiniFileSystem.js.map +1 -1
- package/lib/fs/server/createDatabaseFileSystem.js +7 -7
- package/lib/fs/server/createDatabaseFileSystem.js.map +1 -1
- package/lib/fs/server/createNodeFileSystem.js +30 -5
- package/lib/fs/server/createNodeFileSystem.js.map +1 -1
- package/lib/fs/tests/runFileSystemTest.js +27 -26
- package/lib/fs/tests/runFileSystemTest.js.map +1 -1
- package/lib/fs/utils.js.map +1 -1
- package/lib/fs/webdav/index.js +2 -0
- package/lib/fs/webdav/index.js.map +1 -0
- package/lib/jsonschema/JsonSchema.js +5 -5
- package/lib/jsonschema/JsonSchema.js.map +1 -1
- package/lib/jsonschema/forEachJsonSchema.js +1 -1
- package/lib/jsonschema/forEachJsonSchema.js.map +1 -1
- package/lib/jsonschema/types.d.js.map +1 -1
- package/lib/meta/defineMetadata.js.map +1 -1
- package/lib/orpc/createOpenApiContractClient.js.map +1 -1
- package/lib/password/PHC.js +2 -2
- package/lib/password/PHC.js.map +1 -1
- package/lib/password/createArgon2PasswordAlgorithm.js.map +1 -1
- package/lib/password/createBase64PasswordAlgorithm.js +1 -1
- package/lib/password/createBase64PasswordAlgorithm.js.map +1 -1
- package/lib/password/createBcryptPasswordAlgorithm.js.map +1 -1
- package/lib/password/createPBKDF2PasswordAlgorithm.js +1 -1
- package/lib/password/createPBKDF2PasswordAlgorithm.js.map +1 -1
- package/lib/password/createScryptPasswordAlgorithm.js +3 -3
- package/lib/password/createScryptPasswordAlgorithm.js.map +1 -1
- package/lib/resource/ListQuery.js.map +1 -1
- package/lib/resource/index.js.map +1 -1
- package/lib/s3/formatS3Url.js +2 -2
- package/lib/s3/formatS3Url.js.map +1 -1
- package/lib/s3/parseS3Url.js +1 -1
- package/lib/s3/parseS3Url.js.map +1 -1
- package/lib/schema/SchemaRegistry.js.map +1 -1
- package/lib/schema/TypeSchema.d.js.map +1 -1
- package/lib/schema/createSchemaData.js +4 -4
- package/lib/schema/createSchemaData.js.map +1 -1
- package/lib/schema/findJsonSchemaByPath.js.map +1 -1
- package/lib/schema/formatZodError.js +42 -44
- package/lib/schema/formatZodError.js.map +1 -1
- package/lib/schema/toJsonSchema.js +4 -4
- package/lib/schema/toJsonSchema.js.map +1 -1
- package/lib/schema/validate.js +1 -1
- package/lib/schema/validate.js.map +1 -1
- package/lib/utils/buildRedactorFormSchema.js +1 -1
- package/lib/utils/buildRedactorFormSchema.js.map +1 -1
- package/package.json +32 -13
- package/src/ai/qwen3vl/utils.ts +1 -1
- package/src/cn/ChineseResidentIdNo.ts +1 -1
- package/src/cn/Mod11.ts +1 -1
- package/src/cn/__snapshots__/ChineseResidentIdNo.test.ts.snap +1 -1
- package/src/cn/__snapshots__/UnifiedSocialCreditCode.test.ts.snap +0 -23
- package/src/cn/parseChineseNumber.test.ts +4 -4
- package/src/consola/formatLogObject.ts +6 -6
- package/src/data/maybeNumber.ts +1 -1
- package/src/data/parseSort.test.ts +0 -1
- package/src/data/types.d.ts +2 -2
- package/src/dayjs/formatDuration.ts +2 -2
- package/src/dayjs/resolveRelativeTime.ts +11 -14
- package/src/drain3/Drain.test.ts +378 -0
- package/src/drain3/Drain.ts +394 -0
- package/src/drain3/LogCluster.ts +46 -0
- package/src/drain3/Node.ts +53 -0
- package/src/drain3/TemplateMiner.ts +246 -0
- package/src/drain3/index.ts +36 -0
- package/src/drain3/persistence/FilePersistence.ts +24 -0
- package/src/drain3/persistence/MemoryPersistence.ts +23 -0
- package/src/drain3/persistence/PersistenceHandler.ts +19 -0
- package/src/drain3/types.ts +75 -0
- package/src/fs/IFileSystem.d.ts +1 -2
- package/src/fs/createBrowserFileSystem.ts +7 -5
- package/src/fs/createMemoryFileSystem.ts +9 -13
- package/src/fs/createSandboxFileSystem.ts +1 -1
- package/src/fs/createWebDavFileSystem.ts +28 -10
- package/src/fs/createWebFileSystem.ts +242 -0
- package/src/fs/findMimeType.ts +1 -4
- package/src/fs/index.ts +1 -1
- package/src/fs/minio/createMinioFileSystem.ts +1148 -0
- package/src/fs/minio/index.ts +1 -0
- package/src/fs/orpc/createContractClientFileSystem.ts +5 -5
- package/src/fs/orpc/server/createFileSystemContractImpl.ts +1 -1
- package/src/fs/s3/createS3MiniFileSystem.ts +119 -78
- package/src/fs/s3/s3fs.test.ts +441 -0
- package/src/fs/s3/s3mini.test.ts +2 -2
- package/src/fs/server/createDatabaseFileSystem.ts +7 -7
- package/src/fs/server/createNodeFileSystem.ts +32 -13
- package/src/fs/server/dbfs.test.ts +2 -1
- package/src/fs/tests/runFileSystemTest.ts +29 -28
- package/src/fs/utils.ts +1 -1
- package/src/fs/webdav/index.ts +1 -0
- package/src/jsonschema/JsonSchema.ts +5 -5
- package/src/jsonschema/forEachJsonSchema.ts +1 -1
- package/src/jsonschema/types.d.ts +1 -1
- package/src/meta/defineMetadata.ts +1 -1
- package/src/orpc/createOpenApiContractClient.ts +2 -2
- package/src/password/PHC.ts +3 -3
- package/src/password/createArgon2PasswordAlgorithm.ts +1 -1
- package/src/password/createBase64PasswordAlgorithm.ts +2 -2
- package/src/password/createBcryptPasswordAlgorithm.ts +4 -2
- package/src/password/createPBKDF2PasswordAlgorithm.ts +2 -2
- package/src/password/createScryptPasswordAlgorithm.ts +4 -4
- package/src/resource/ListQuery.ts +4 -1
- package/src/resource/index.ts +2 -2
- package/src/s3/formatS3Url.test.ts +1 -1
- package/src/s3/formatS3Url.ts +2 -2
- package/src/s3/parseS3Url.ts +1 -1
- package/src/schema/SchemaRegistry.ts +1 -1
- package/src/schema/TypeSchema.d.ts +6 -6
- package/src/schema/createSchemaData.ts +4 -4
- package/src/schema/findJsonSchemaByPath.ts +4 -4
- package/src/schema/formatZodError.test.ts +2 -1
- package/src/schema/formatZodError.ts +50 -62
- package/src/schema/toJsonSchema.ts +6 -6
- package/src/schema/validate.ts +1 -1
- package/src/utils/buildRedactorFormSchema.ts +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/fs/createMemoryFileSystem.ts"],"sourcesContent":["import type { Readable, Writable } from 'node:stream';\nimport { computeIfAbsent } from '@wener/utils';\nimport { basename, dirname, normalize } from 'pathe';\nimport { findMimeType } from './findMimeType';\nimport type {\n\tCopyOptions,\n\tCreateReadStreamOptions,\n\tCreateWriteStreamOptions,\n\tIFileStat,\n\tIFileSystem,\n\tMkdirOptions,\n\tReadFileOptions,\n\tRenameOptions,\n\tRmOptions,\n\tWriteFileOptions,\n} from './IFileSystem';\n\ntype MemoryNode = MemoryFile | MemoryDirectory;\n\ntype MemoryFile = IFileStat & {\n\tkind: 'file';\n\tcontent: string | Buffer;\n};\n\ntype MemoryDirectory = IFileStat & {\n\tkind: 'directory';\n\tchildren: MemoryNode[];\n};\n\nexport function createMemoryFileSystem(\n\toptions: {\n\t\troot?: MemoryDirectory;\n\t} = {},\n): IFileSystem {\n\treturn new MemFS(options);\n}\n\nclass MemoryFileSystemError extends Error {\n\tcode?: string;\n\n\tconstructor(message: string, code?: string) {\n\t\tsuper(message);\n\t\tthis.name = 'MemoryFileSystemError';\n\t\tthis.code = code;\n\t}\n}\n\ntype Cache = {\n\turl?: string;\n};\n\nclass MemFS implements IFileSystem {\n\tprivate readonly root: MemoryDirectory;\n\n\tprivate readonly cache = new WeakMap<MemoryNode, Cache>();\n\n\tconstructor({\n\t\troot,\n\t}: {\n\t\troot?: MemoryDirectory;\n\t} = {}) {\n\t\tthis.root = root || {\n\t\t\tname: '',\n\t\t\tkind: 'directory',\n\t\t\tpath: '/',\n\t\t\tdirectory: '',\n\t\t\tchildren: [],\n\t\t\tsize: 0,\n\t\t\tmtime: Date.now(),\n\t\t\tmeta: {},\n\t\t};\n\t}\n\n\t/**\n\t * 核心辅助方法:通过路径查找节点\n\t * @returns A tuple: [foundNode, parentNode, finalName]\n\t */\n\tprivate _getNodeByPath(path: string): [MemoryNode | null, MemoryDirectory | null, string] {\n\t\tif (!path || typeof path !== 'string') {\n\t\t\tthrow new MemoryFileSystemError('Invalid path: path must be a non-empty string', 'EINVAL');\n\t\t}\n\n\t\tconst normalized = normalize(path);\n\t\tif (normalized === '/') {\n\t\t\t// the parent of root is itself\n\t\t\treturn [this.root, this.root, ''];\n\t\t}\n\n\t\tconst parts = normalized.split('/').filter((p) => p);\n\t\tif (parts.length === 0) {\n\t\t\treturn [this.root, this.root, ''];\n\t\t}\n\n\t\tconst finalName = parts.pop()!;\n\n\t\tlet current: MemoryDirectory = this.root;\n\t\tfor (const part of parts) {\n\t\t\tif (!part) continue; // skip empty parts\n\n\t\t\tconst found = current.children.find((child) => child.name === part);\n\t\t\tif (!found || found.kind !== 'directory') {\n\t\t\t\treturn [null, null, finalName];\n\t\t\t}\n\t\t\tcurrent = found;\n\t\t}\n\n\t\tconst node = current.children.find((child) => child.name === finalName) ?? null;\n\t\treturn [node, current, finalName];\n\t}\n\n\t/**\n\t * 核心辅助方法:查找或创建目录\n\t */\n\tprivate _findOrCreateDirectory(path: string): MemoryDirectory {\n\t\tif (!path || typeof path !== 'string') {\n\t\t\tthrow new MemoryFileSystemError('Invalid path: path must be a non-empty string', 'EINVAL');\n\t\t}\n\n\t\tconst normalized = normalize(path);\n\t\tif (normalized === '/') return this.root;\n\n\t\tconst parts = normalized.split('/').filter((p) => p);\n\t\tif (parts.length === 0) return this.root;\n\n\t\tlet current: MemoryDirectory = this.root;\n\t\tlet currentPath = '';\n\n\t\tfor (const part of parts) {\n\t\t\tif (!part) continue; // skip empty parts\n\n\t\t\tcurrentPath = `${currentPath}/${part}`;\n\t\t\tlet found = current.children.find((child) => child.name === part);\n\t\t\tif (!found) {\n\t\t\t\tconst now = Date.now();\n\t\t\t\tconst newDir: MemoryDirectory = {\n\t\t\t\t\tname: part,\n\t\t\t\t\tkind: 'directory',\n\t\t\t\t\tpath: currentPath,\n\t\t\t\t\tdirectory: dirname(currentPath),\n\t\t\t\t\tchildren: [],\n\t\t\t\t\tsize: 0,\n\t\t\t\t\tmtime: now,\n\t\t\t\t\tmeta: {},\n\t\t\t\t};\n\t\t\t\tcurrent.children.push(newDir);\n\t\t\t\tcurrent = newDir;\n\t\t\t} else if (found.kind !== 'directory') {\n\t\t\t\tthrow new MemoryFileSystemError(`Path conflict: ${currentPath} is a file`, 'ENOTDIR');\n\t\t\t} else {\n\t\t\t\tcurrent = found;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t}\n\n\tasync stat(path: string, options?: { signal?: AbortSignal }): Promise<IFileStat> {\n\t\tif (options?.signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst [node] = this._getNodeByPath(path);\n\t\tif (!node) {\n\t\t\tthrow new MemoryFileSystemError(`File not found: ${path}`, 'ENOENT');\n\t\t}\n\t\treturn { ...node };\n\t}\n\n\tasync exists(path: string): Promise<boolean> {\n\t\tconst [node] = this._getNodeByPath(path);\n\t\treturn !!node;\n\t}\n\n\tasync readdir(path: string, options?: { signal?: AbortSignal }): Promise<IFileStat[]> {\n\t\tif (options?.signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst [node] = this._getNodeByPath(path);\n\t\tif (!node) {\n\t\t\tthrow new MemoryFileSystemError(`Directory not found: ${path}`, 'ENOENT');\n\t\t}\n\t\tif (node.kind !== 'directory') {\n\t\t\tthrow new MemoryFileSystemError(`Not a directory: ${path}`, 'ENOTDIR');\n\t\t}\n\t\t// 返回副本\n\t\treturn node.children.map((child) => ({ ...child }));\n\t}\n\n\tasync mkdir(path: string, options?: MkdirOptions): Promise<void> {\n\t\tif (options?.signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst [node] = this._getNodeByPath(path);\n\t\tif (node) {\n\t\t\tif (node.kind === 'file') throw new MemoryFileSystemError(`File already exists: ${path}`, 'EEXIST');\n\t\t\treturn; // 目录已存在\n\t\t}\n\n\t\tif (options?.recursive) {\n\t\t\tthis._findOrCreateDirectory(path);\n\t\t} else {\n\t\t\tconst parentPath = dirname(path);\n\t\t\tconst [, parent] = this._getNodeByPath(parentPath);\n\t\t\tif (!parent) {\n\t\t\t\tthrow new MemoryFileSystemError(`Parent directory does not exist: ${parentPath}`, 'ENOENT');\n\t\t\t}\n\t\t\tthis._findOrCreateDirectory(path);\n\t\t}\n\t}\n\n\treadFile(path: string, options?: ReadFileOptions & { encoding: 'text' }): Promise<string>;\n\treadFile(path: string, options?: ReadFileOptions): Promise<Uint8Array>;\n\tasync readFile(path: string, options?: ReadFileOptions): Promise<string | Uint8Array> {\n\t\tif (options?.signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst [node] = this._getNodeByPath(path);\n\t\tif (!node) {\n\t\t\tthrow new MemoryFileSystemError(`File not found: ${path}`, 'ENOENT');\n\t\t}\n\t\tif (node.kind !== 'file') {\n\t\t\tthrow new MemoryFileSystemError(`Is a directory: ${path}`, 'EISDIR');\n\t\t}\n\n\t\tconst content = 'content' in node ? node.content : '';\n\t\treturn options?.encoding === 'text' ? content.toString() : Buffer.from(content);\n\t}\n\n\tasync writeFile(path: string, data: string | Buffer, options: WriteFileOptions = {}): Promise<void> {\n\t\tif (options?.signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tif (!path || typeof path !== 'string') {\n\t\t\tthrow new MemoryFileSystemError('Invalid path: path must be a non-empty string', 'EINVAL');\n\t\t}\n\n\t\tif (data === null || data === undefined) {\n\t\t\tthrow new MemoryFileSystemError('Invalid data: data cannot be null or undefined', 'EINVAL');\n\t\t}\n\n\t\tconst { overwrite = true } = options;\n\t\tconst parentPath = dirname(path);\n\t\tconst filename = basename(path);\n\n\t\tif (!filename) {\n\t\t\tthrow new MemoryFileSystemError('Invalid path: filename cannot be empty', 'EINVAL');\n\t\t}\n\n\t\tconst parent = this._findOrCreateDirectory(parentPath);\n\t\tconst nodeIndex = parent.children.findIndex((child) => child.name === filename);\n\t\tconst existingNode = nodeIndex !== -1 ? parent.children[nodeIndex] : null;\n\n\t\tif (existingNode) {\n\t\t\tif (!overwrite) throw new MemoryFileSystemError(`File already exists: ${path}`, 'EEXIST');\n\t\t\tif (existingNode.kind === 'directory')\n\t\t\t\tthrow new MemoryFileSystemError(`Cannot overwrite a directory: ${path}`, 'EISDIR');\n\n\t\t\t// 更新文件\n\t\t\texistingNode.content = data;\n\t\t\texistingNode.size = data.length;\n\t\t\texistingNode.mtime = Date.now();\n\t\t} else {\n\t\t\t// 创建新文件\n\t\t\tconst now = Date.now();\n\t\t\tconst newFile: MemoryFile = {\n\t\t\t\tname: filename,\n\t\t\t\tkind: 'file',\n\t\t\t\tpath: path,\n\t\t\t\tdirectory: parentPath,\n\t\t\t\tcontent: data,\n\t\t\t\tsize: data.length,\n\t\t\t\tmtime: now,\n\t\t\t\tmeta: {},\n\t\t\t};\n\t\t\tparent.children.push(newFile);\n\t\t}\n\t}\n\n\tasync rm(path: string, options: RmOptions = {}): Promise<void> {\n\t\tif (options?.signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst { recursive = false, force = false } = options;\n\t\tconst [node, parent] = this._getNodeByPath(path);\n\n\t\tif (!node) {\n\t\t\tif (force) return;\n\t\t\tthrow new MemoryFileSystemError(`File not found: ${path}`, 'ENOENT');\n\t\t}\n\n\t\tif (node.kind === 'directory' && node.children.length > 0 && !recursive) {\n\t\t\tthrow new MemoryFileSystemError(`Directory not empty: ${path}`, 'ENOTEMPTY');\n\t\t}\n\n\t\tif (parent) {\n\t\t\tconst index = parent.children.findIndex((child) => child.name === node.name);\n\t\t\tif (index !== -1) {\n\t\t\t\tparent.children.splice(index, 1);\n\t\t\t}\n\t\t}\n\t}\n\n\tasync rename(oldPath: string, newPath: string, options?: RenameOptions): Promise<void> {\n\t\tif (options?.signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst [oldNode, oldParent, oldName] = this._getNodeByPath(oldPath);\n\t\tif (!oldNode || !oldParent) throw new MemoryFileSystemError(`Source not found: ${oldPath}`, 'ENOENT');\n\n\t\tconst oldNodeIndex = oldParent.children.findIndex((c) => c.name === oldName);\n\t\toldParent.children.splice(oldNodeIndex, 1);\n\n\t\tconst newParentPath = dirname(newPath);\n\t\tconst newName = basename(newPath);\n\t\tconst newParent = this._findOrCreateDirectory(newParentPath);\n\n\t\tconst existingNodeIndex = newParent.children.findIndex((c) => c.name === newName);\n\t\tif (existingNodeIndex !== -1) {\n\t\t\tif (!options?.overwrite) throw new MemoryFileSystemError(`Destination exists: ${newPath}`, 'EEXIST');\n\t\t\tnewParent.children.splice(existingNodeIndex, 1);\n\t\t}\n\n\t\toldNode.name = newName;\n\t\toldNode.path = newPath;\n\t\toldNode.directory = newParentPath;\n\t\toldNode.mtime = Date.now();\n\t\tnewParent.children.push(oldNode);\n\t}\n\n\tasync copy(srcPath: string, destPath: string, options?: CopyOptions): Promise<void> {\n\t\tif (options?.signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst [srcNode] = this._getNodeByPath(srcPath);\n\t\tif (!srcNode) throw new MemoryFileSystemError(`Source not found: ${srcPath}`, 'ENOENT');\n\n\t\tconst deepClone = <T extends MemoryNode>(node: T): T => JSON.parse(JSON.stringify(node));\n\t\tconst newNode = deepClone(srcNode);\n\n\t\tconst newParentPath = dirname(destPath);\n\t\tconst newName = basename(destPath);\n\t\tconst newParent = this._findOrCreateDirectory(newParentPath);\n\n\t\tnewNode.name = newName;\n\t\tnewNode.path = destPath;\n\t\tnewNode.directory = newParentPath;\n\n\t\tconst existingNodeIndex = newParent.children.findIndex((c) => c.name === newName);\n\t\tif (existingNodeIndex !== -1) {\n\t\t\tif (!options?.overwrite) throw new MemoryFileSystemError(`Destination exists: ${destPath}`, 'EEXIST');\n\t\t\tnewParent.children[existingNodeIndex] = newNode;\n\t\t} else {\n\t\t\tnewParent.children.push(newNode);\n\t\t}\n\t}\n\n\tcreateReadStream(path: string, options?: CreateReadStreamOptions): Readable {\n\t\tconst { signal, range } = options || {};\n\n\t\tif (signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst [node] = this._getNodeByPath(path);\n\t\tif (!node) {\n\t\t\tthrow new MemoryFileSystemError(`File not found: ${path}`, 'ENOENT');\n\t\t}\n\t\tif (node.kind !== 'file') {\n\t\t\tthrow new MemoryFileSystemError(`Is a directory: ${path}`, 'EISDIR');\n\t\t}\n\n\t\tconst content = Buffer.from('content' in node ? node.content : '');\n\t\tconst { Readable } = require('node:stream');\n\n\t\tlet data = content;\n\t\tif (range) {\n\t\t\tconst start = range.start || 0;\n\t\t\tconst end = range.end || content.length - 1;\n\t\t\tdata = content.subarray(start, end + 1);\n\t\t}\n\n\t\tconst stream = Readable.from([data]);\n\n\t\tif (signal) {\n\t\t\tsignal.addEventListener('abort', () => {\n\t\t\t\tstream.destroy(new MemoryFileSystemError('Operation aborted', 'ABORT_ERR'));\n\t\t\t});\n\t\t}\n\n\t\treturn stream;\n\t}\n\n\tcreateWriteStream(path: string, options?: CreateWriteStreamOptions): Writable {\n\t\tconst { signal, overwrite = true } = options || {};\n\n\t\tif (signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst { Writable } = require('node:stream');\n\t\tconst chunks: Buffer[] = [];\n\n\t\tconst self = this;\n\t\tconst stream = new Writable({\n\t\t\twrite(chunk: Buffer, encoding: BufferEncoding, callback: (error?: Error | null) => void) {\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tcallback(new MemoryFileSystemError('Operation aborted', 'ABORT_ERR'));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tchunks.push(chunk);\n\t\t\t\tcallback();\n\t\t\t},\n\t\t\tfinal(callback: (error?: Error | null) => void) {\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tcallback(new MemoryFileSystemError('Operation aborted', 'ABORT_ERR'));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst content = Buffer.concat(chunks);\n\t\t\t\t\tconst parentPath = dirname(path);\n\t\t\t\t\tconst filename = basename(path);\n\t\t\t\t\tconst parent = self._findOrCreateDirectory(parentPath);\n\n\t\t\t\t\tconst nodeIndex = parent.children.findIndex((child) => child.name === filename);\n\t\t\t\t\tconst existingNode = nodeIndex !== -1 ? parent.children[nodeIndex] : null;\n\n\t\t\t\t\tif (existingNode) {\n\t\t\t\t\t\tif (!overwrite) {\n\t\t\t\t\t\t\tcallback(new MemoryFileSystemError(`File already exists: ${path}`, 'EEXIST'));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (existingNode.kind === 'directory') {\n\t\t\t\t\t\t\tcallback(new MemoryFileSystemError(`Cannot overwrite a directory: ${path}`, 'EISDIR'));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\texistingNode.content = content;\n\t\t\t\t\t\texistingNode.size = content.length;\n\t\t\t\t\t\texistingNode.mtime = Date.now();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst now = Date.now();\n\t\t\t\t\t\tconst newFile: MemoryFile = {\n\t\t\t\t\t\t\tname: filename,\n\t\t\t\t\t\t\tkind: 'file',\n\t\t\t\t\t\t\tpath: path,\n\t\t\t\t\t\t\tdirectory: parentPath,\n\t\t\t\t\t\t\tcontent: content,\n\t\t\t\t\t\t\tsize: content.length,\n\t\t\t\t\t\t\tmtime: now,\n\t\t\t\t\t\t\tmeta: {},\n\t\t\t\t\t\t};\n\t\t\t\t\t\tparent.children.push(newFile);\n\t\t\t\t\t}\n\n\t\t\t\t\tcallback();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tcallback(error instanceof Error ? error : new MemoryFileSystemError('Unknown error', 'UNKNOWN'));\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\n\t\tif (signal) {\n\t\t\tsignal.addEventListener('abort', () => {\n\t\t\t\tstream.destroy(new MemoryFileSystemError('Operation aborted', 'ABORT_ERR'));\n\t\t\t});\n\t\t}\n\n\t\treturn stream;\n\t}\n\n\tgetUrl(file: IFileStat | string) {\n\t\tlet node: IFileStat | null;\n\t\tif (typeof file === 'string') {\n\t\t\t[node] = this._getNodeByPath(file);\n\t\t} else {\n\t\t\tnode = file;\n\t\t}\n\t\tlet mf = node as MemoryFile;\n\t\tif (mf.content) {\n\t\t\tlet c = computeIfAbsent(this.cache, mf, () => ({}) as Cache);\n\t\t\tif (!c.url) {\n\t\t\t\tlet mime = findMimeType(mf.name) || 'application/octet-stream';\n\t\t\t\tc.url = URL.createObjectURL(new Blob([mf.content], { type: mime }));\n\t\t\t}\n\n\t\t\treturn c.url;\n\t\t}\n\t\treturn;\n\t}\n\n\tcreateReadableStream(path: string, options?: CreateReadStreamOptions): ReadableStream {\n\t\tconst { signal, range } = options || {};\n\n\t\tif (signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst [node] = this._getNodeByPath(path);\n\t\tif (!node) {\n\t\t\tthrow new MemoryFileSystemError(`File not found: ${path}`, 'ENOENT');\n\t\t}\n\t\tif (node.kind !== 'file') {\n\t\t\tthrow new MemoryFileSystemError(`Is a directory: ${path}`, 'EISDIR');\n\t\t}\n\n\t\tconst content = Buffer.from('content' in node ? node.content : '');\n\n\t\tlet data = content;\n\t\tif (range) {\n\t\t\tconst start = range.start || 0;\n\t\t\tconst end = range.end || content.length - 1;\n\t\t\tdata = content.subarray(start, end + 1);\n\t\t}\n\n\t\tconst stream = new ReadableStream({\n\t\t\tstart(controller) {\n\t\t\t\tcontroller.enqueue(data);\n\t\t\t\tcontroller.close();\n\t\t\t},\n\t\t});\n\n\t\tif (signal) {\n\t\t\tsignal.addEventListener('abort', () => {\n\t\t\t\tstream.cancel(new MemoryFileSystemError('Operation aborted', 'ABORT_ERR'));\n\t\t\t});\n\t\t}\n\n\t\treturn stream;\n\t}\n\n\tcreateWritableStream(path: string, options?: CreateWriteStreamOptions): WritableStream {\n\t\tconst { signal, overwrite = true } = options || {};\n\n\t\tif (signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst chunks: Buffer[] = [];\n\n\t\tconst self = this;\n\t\tconst stream = new WritableStream({\n\t\t\twrite(chunk: Buffer) {\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t\t\t}\n\t\t\t\tchunks.push(chunk);\n\t\t\t},\n\t\t\tclose() {\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t\t\t}\n\n\t\t\t\tconst content = Buffer.concat(chunks);\n\t\t\t\tconst parentPath = dirname(path);\n\t\t\t\tconst filename = basename(path);\n\t\t\t\tconst parent = self._findOrCreateDirectory(parentPath);\n\n\t\t\t\tconst nodeIndex = parent.children.findIndex((child) => child.name === filename);\n\t\t\t\tconst existingNode = nodeIndex !== -1 ? parent.children[nodeIndex] : null;\n\n\t\t\t\tif (existingNode) {\n\t\t\t\t\tif (!overwrite) {\n\t\t\t\t\t\tthrow new MemoryFileSystemError(`File already exists: ${path}`, 'EEXIST');\n\t\t\t\t\t}\n\t\t\t\t\tif (existingNode.kind === 'directory') {\n\t\t\t\t\t\tthrow new MemoryFileSystemError(`Cannot overwrite a directory: ${path}`, 'EISDIR');\n\t\t\t\t\t}\n\n\t\t\t\t\texistingNode.content = content;\n\t\t\t\t\texistingNode.size = content.length;\n\t\t\t\t\texistingNode.mtime = Date.now();\n\t\t\t\t} else {\n\t\t\t\t\tconst now = Date.now();\n\t\t\t\t\tconst newFile: MemoryFile = {\n\t\t\t\t\t\tname: filename,\n\t\t\t\t\t\tkind: 'file',\n\t\t\t\t\t\tpath: path,\n\t\t\t\t\t\tdirectory: parentPath,\n\t\t\t\t\t\tcontent: content,\n\t\t\t\t\t\tsize: content.length,\n\t\t\t\t\t\tmtime: now,\n\t\t\t\t\t\tmeta: {},\n\t\t\t\t\t};\n\t\t\t\t\tparent.children.push(newFile);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\n\t\tif (signal) {\n\t\t\tsignal.addEventListener('abort', () => {\n\t\t\t\tstream.abort(new MemoryFileSystemError('Operation aborted', 'ABORT_ERR'));\n\t\t\t});\n\t\t}\n\n\t\treturn stream;\n\t}\n}\n"],"names":["computeIfAbsent","basename","dirname","normalize","findMimeType","createMemoryFileSystem","options","MemFS","MemoryFileSystemError","Error","code","message","name","root","cache","WeakMap","kind","path","directory","children","size","mtime","Date","now","meta","_getNodeByPath","normalized","parts","split","filter","p","length","finalName","pop","current","part","found","find","child","node","_findOrCreateDirectory","currentPath","newDir","push","stat","signal","aborted","exists","readdir","map","mkdir","recursive","parentPath","parent","readFile","content","encoding","toString","Buffer","from","writeFile","data","undefined","overwrite","filename","nodeIndex","findIndex","existingNode","newFile","rm","force","index","splice","rename","oldPath","newPath","oldNode","oldParent","oldName","oldNodeIndex","c","newParentPath","newName","newParent","existingNodeIndex","copy","srcPath","destPath","srcNode","deepClone","JSON","parse","stringify","newNode","createReadStream","range","Readable","require","start","end","subarray","stream","addEventListener","destroy","createWriteStream","Writable","chunks","self","write","chunk","callback","final","concat","error","getUrl","file","mf","url","mime","URL","createObjectURL","Blob","type","createReadableStream","ReadableStream","controller","enqueue","close","cancel","createWritableStream","WritableStream","abort"],"mappings":"AACA,SAASA,eAAe,QAAQ,eAAe;AAC/C,SAASC,QAAQ,EAAEC,OAAO,EAAEC,SAAS,QAAQ,QAAQ;AACrD,SAASC,YAAY,QAAQ,iBAAiB;AA0B9C,OAAO,SAASC,uBACfC,UAEI,CAAC,CAAC;IAEN,OAAO,IAAIC,MAAMD;AAClB;AAEA,IAAA,AAAME,wBAAN,MAAMA,8BAA8BC;IACnCC,KAAc;IAEd,YAAYC,OAAe,EAAED,IAAa,CAAE;QAC3C,KAAK,CAACC;QACN,IAAI,CAACC,IAAI,GAAG;QACZ,IAAI,CAACF,IAAI,GAAGA;IACb;AACD;AAMA,IAAA,AAAMH,QAAN,MAAMA;IACYM,KAAsB;IAEtBC,QAAQ,IAAIC,UAA6B;IAE1D,YAAY,EACXF,IAAI,EAGJ,GAAG,CAAC,CAAC,CAAE;QACP,IAAI,CAACA,IAAI,GAAGA,QAAQ;YACnBD,MAAM;YACNI,MAAM;YACNC,MAAM;YACNC,WAAW;YACXC,UAAU,EAAE;YACZC,MAAM;YACNC,OAAOC,KAAKC,GAAG;YACfC,MAAM,CAAC;QACR;IACD;IAEA;;;EAGC,GACD,AAAQC,eAAeR,IAAY,EAAuD;QACzF,IAAI,CAACA,QAAQ,OAAOA,SAAS,UAAU;YACtC,MAAM,IAAIT,sBAAsB,iDAAiD;QAClF;QAEA,MAAMkB,aAAavB,UAAUc;QAC7B,IAAIS,eAAe,KAAK;YACvB,+BAA+B;YAC/B,OAAO;gBAAC,IAAI,CAACb,IAAI;gBAAE,IAAI,CAACA,IAAI;gBAAE;aAAG;QAClC;QAEA,MAAMc,QAAQD,WAAWE,KAAK,CAAC,KAAKC,MAAM,CAAC,CAACC,IAAMA;QAClD,IAAIH,MAAMI,MAAM,KAAK,GAAG;YACvB,OAAO;gBAAC,IAAI,CAAClB,IAAI;gBAAE,IAAI,CAACA,IAAI;gBAAE;aAAG;QAClC;QAEA,MAAMmB,YAAYL,MAAMM,GAAG;QAE3B,IAAIC,UAA2B,IAAI,CAACrB,IAAI;QACxC,KAAK,MAAMsB,QAAQR,MAAO;YACzB,IAAI,CAACQ,MAAM,UAAU,mBAAmB;YAExC,MAAMC,QAAQF,QAAQf,QAAQ,CAACkB,IAAI,CAAC,CAACC,QAAUA,MAAM1B,IAAI,KAAKuB;YAC9D,IAAI,CAACC,SAASA,MAAMpB,IAAI,KAAK,aAAa;gBACzC,OAAO;oBAAC;oBAAM;oBAAMgB;iBAAU;YAC/B;YACAE,UAAUE;QACX;QAEA,MAAMG,OAAOL,QAAQf,QAAQ,CAACkB,IAAI,CAAC,CAACC,QAAUA,MAAM1B,IAAI,KAAKoB,cAAc;QAC3E,OAAO;YAACO;YAAML;YAASF;SAAU;IAClC;IAEA;;EAEC,GACD,AAAQQ,uBAAuBvB,IAAY,EAAmB;QAC7D,IAAI,CAACA,QAAQ,OAAOA,SAAS,UAAU;YACtC,MAAM,IAAIT,sBAAsB,iDAAiD;QAClF;QAEA,MAAMkB,aAAavB,UAAUc;QAC7B,IAAIS,eAAe,KAAK,OAAO,IAAI,CAACb,IAAI;QAExC,MAAMc,QAAQD,WAAWE,KAAK,CAAC,KAAKC,MAAM,CAAC,CAACC,IAAMA;QAClD,IAAIH,MAAMI,MAAM,KAAK,GAAG,OAAO,IAAI,CAAClB,IAAI;QAExC,IAAIqB,UAA2B,IAAI,CAACrB,IAAI;QACxC,IAAI4B,cAAc;QAElB,KAAK,MAAMN,QAAQR,MAAO;YACzB,IAAI,CAACQ,MAAM,UAAU,mBAAmB;YAExCM,cAAc,GAAGA,YAAY,CAAC,EAAEN,MAAM;YACtC,IAAIC,QAAQF,QAAQf,QAAQ,CAACkB,IAAI,CAAC,CAACC,QAAUA,MAAM1B,IAAI,KAAKuB;YAC5D,IAAI,CAACC,OAAO;gBACX,MAAMb,MAAMD,KAAKC,GAAG;gBACpB,MAAMmB,SAA0B;oBAC/B9B,MAAMuB;oBACNnB,MAAM;oBACNC,MAAMwB;oBACNvB,WAAWhB,QAAQuC;oBACnBtB,UAAU,EAAE;oBACZC,MAAM;oBACNC,OAAOE;oBACPC,MAAM,CAAC;gBACR;gBACAU,QAAQf,QAAQ,CAACwB,IAAI,CAACD;gBACtBR,UAAUQ;YACX,OAAO,IAAIN,MAAMpB,IAAI,KAAK,aAAa;gBACtC,MAAM,IAAIR,sBAAsB,CAAC,eAAe,EAAEiC,YAAY,UAAU,CAAC,EAAE;YAC5E,OAAO;gBACNP,UAAUE;YACX;QACD;QACA,OAAOF;IACR;IAEA,MAAMU,KAAK3B,IAAY,EAAEX,OAAkC,EAAsB;QAChF,IAAIA,SAASuC,QAAQC,SAAS;YAC7B,MAAM,IAAItC,sBAAsB,qBAAqB;QACtD;QAEA,MAAM,CAAC+B,KAAK,GAAG,IAAI,CAACd,cAAc,CAACR;QACnC,IAAI,CAACsB,MAAM;YACV,MAAM,IAAI/B,sBAAsB,CAAC,gBAAgB,EAAES,MAAM,EAAE;QAC5D;QACA,OAAO;YAAE,GAAGsB,IAAI;QAAC;IAClB;IAEA,MAAMQ,OAAO9B,IAAY,EAAoB;QAC5C,MAAM,CAACsB,KAAK,GAAG,IAAI,CAACd,cAAc,CAACR;QACnC,OAAO,CAAC,CAACsB;IACV;IAEA,MAAMS,QAAQ/B,IAAY,EAAEX,OAAkC,EAAwB;QACrF,IAAIA,SAASuC,QAAQC,SAAS;YAC7B,MAAM,IAAItC,sBAAsB,qBAAqB;QACtD;QAEA,MAAM,CAAC+B,KAAK,GAAG,IAAI,CAACd,cAAc,CAACR;QACnC,IAAI,CAACsB,MAAM;YACV,MAAM,IAAI/B,sBAAsB,CAAC,qBAAqB,EAAES,MAAM,EAAE;QACjE;QACA,IAAIsB,KAAKvB,IAAI,KAAK,aAAa;YAC9B,MAAM,IAAIR,sBAAsB,CAAC,iBAAiB,EAAES,MAAM,EAAE;QAC7D;QACA,OAAO;QACP,OAAOsB,KAAKpB,QAAQ,CAAC8B,GAAG,CAAC,CAACX,QAAW,CAAA;gBAAE,GAAGA,KAAK;YAAC,CAAA;IACjD;IAEA,MAAMY,MAAMjC,IAAY,EAAEX,OAAsB,EAAiB;QAChE,IAAIA,SAASuC,QAAQC,SAAS;YAC7B,MAAM,IAAItC,sBAAsB,qBAAqB;QACtD;QAEA,MAAM,CAAC+B,KAAK,GAAG,IAAI,CAACd,cAAc,CAACR;QACnC,IAAIsB,MAAM;YACT,IAAIA,KAAKvB,IAAI,KAAK,QAAQ,MAAM,IAAIR,sBAAsB,CAAC,qBAAqB,EAAES,MAAM,EAAE;YAC1F,QAAQ,QAAQ;QACjB;QAEA,IAAIX,SAAS6C,WAAW;YACvB,IAAI,CAACX,sBAAsB,CAACvB;QAC7B,OAAO;YACN,MAAMmC,aAAalD,QAAQe;YAC3B,MAAM,GAAGoC,OAAO,GAAG,IAAI,CAAC5B,cAAc,CAAC2B;YACvC,IAAI,CAACC,QAAQ;gBACZ,MAAM,IAAI7C,sBAAsB,CAAC,iCAAiC,EAAE4C,YAAY,EAAE;YACnF;YACA,IAAI,CAACZ,sBAAsB,CAACvB;QAC7B;IACD;IAIA,MAAMqC,SAASrC,IAAY,EAAEX,OAAyB,EAAgC;QACrF,IAAIA,SAASuC,QAAQC,SAAS;YAC7B,MAAM,IAAItC,sBAAsB,qBAAqB;QACtD;QAEA,MAAM,CAAC+B,KAAK,GAAG,IAAI,CAACd,cAAc,CAACR;QACnC,IAAI,CAACsB,MAAM;YACV,MAAM,IAAI/B,sBAAsB,CAAC,gBAAgB,EAAES,MAAM,EAAE;QAC5D;QACA,IAAIsB,KAAKvB,IAAI,KAAK,QAAQ;YACzB,MAAM,IAAIR,sBAAsB,CAAC,gBAAgB,EAAES,MAAM,EAAE;QAC5D;QAEA,MAAMsC,UAAU,aAAahB,OAAOA,KAAKgB,OAAO,GAAG;QACnD,OAAOjD,SAASkD,aAAa,SAASD,QAAQE,QAAQ,KAAKC,OAAOC,IAAI,CAACJ;IACxE;IAEA,MAAMK,UAAU3C,IAAY,EAAE4C,IAAqB,EAAEvD,UAA4B,CAAC,CAAC,EAAiB;QACnG,IAAIA,SAASuC,QAAQC,SAAS;YAC7B,MAAM,IAAItC,sBAAsB,qBAAqB;QACtD;QAEA,IAAI,CAACS,QAAQ,OAAOA,SAAS,UAAU;YACtC,MAAM,IAAIT,sBAAsB,iDAAiD;QAClF;QAEA,IAAIqD,SAAS,QAAQA,SAASC,WAAW;YACxC,MAAM,IAAItD,sBAAsB,kDAAkD;QACnF;QAEA,MAAM,EAAEuD,YAAY,IAAI,EAAE,GAAGzD;QAC7B,MAAM8C,aAAalD,QAAQe;QAC3B,MAAM+C,WAAW/D,SAASgB;QAE1B,IAAI,CAAC+C,UAAU;YACd,MAAM,IAAIxD,sBAAsB,0CAA0C;QAC3E;QAEA,MAAM6C,SAAS,IAAI,CAACb,sBAAsB,CAACY;QAC3C,MAAMa,YAAYZ,OAAOlC,QAAQ,CAAC+C,SAAS,CAAC,CAAC5B,QAAUA,MAAM1B,IAAI,KAAKoD;QACtE,MAAMG,eAAeF,cAAc,CAAC,IAAIZ,OAAOlC,QAAQ,CAAC8C,UAAU,GAAG;QAErE,IAAIE,cAAc;YACjB,IAAI,CAACJ,WAAW,MAAM,IAAIvD,sBAAsB,CAAC,qBAAqB,EAAES,MAAM,EAAE;YAChF,IAAIkD,aAAanD,IAAI,KAAK,aACzB,MAAM,IAAIR,sBAAsB,CAAC,8BAA8B,EAAES,MAAM,EAAE;YAE1E,OAAO;YACPkD,aAAaZ,OAAO,GAAGM;YACvBM,aAAa/C,IAAI,GAAGyC,KAAK9B,MAAM;YAC/BoC,aAAa9C,KAAK,GAAGC,KAAKC,GAAG;QAC9B,OAAO;YACN,QAAQ;YACR,MAAMA,MAAMD,KAAKC,GAAG;YACpB,MAAM6C,UAAsB;gBAC3BxD,MAAMoD;gBACNhD,MAAM;gBACNC,MAAMA;gBACNC,WAAWkC;gBACXG,SAASM;gBACTzC,MAAMyC,KAAK9B,MAAM;gBACjBV,OAAOE;gBACPC,MAAM,CAAC;YACR;YACA6B,OAAOlC,QAAQ,CAACwB,IAAI,CAACyB;QACtB;IACD;IAEA,MAAMC,GAAGpD,IAAY,EAAEX,UAAqB,CAAC,CAAC,EAAiB;QAC9D,IAAIA,SAASuC,QAAQC,SAAS;YAC7B,MAAM,IAAItC,sBAAsB,qBAAqB;QACtD;QAEA,MAAM,EAAE2C,YAAY,KAAK,EAAEmB,QAAQ,KAAK,EAAE,GAAGhE;QAC7C,MAAM,CAACiC,MAAMc,OAAO,GAAG,IAAI,CAAC5B,cAAc,CAACR;QAE3C,IAAI,CAACsB,MAAM;YACV,IAAI+B,OAAO;YACX,MAAM,IAAI9D,sBAAsB,CAAC,gBAAgB,EAAES,MAAM,EAAE;QAC5D;QAEA,IAAIsB,KAAKvB,IAAI,KAAK,eAAeuB,KAAKpB,QAAQ,CAACY,MAAM,GAAG,KAAK,CAACoB,WAAW;YACxE,MAAM,IAAI3C,sBAAsB,CAAC,qBAAqB,EAAES,MAAM,EAAE;QACjE;QAEA,IAAIoC,QAAQ;YACX,MAAMkB,QAAQlB,OAAOlC,QAAQ,CAAC+C,SAAS,CAAC,CAAC5B,QAAUA,MAAM1B,IAAI,KAAK2B,KAAK3B,IAAI;YAC3E,IAAI2D,UAAU,CAAC,GAAG;gBACjBlB,OAAOlC,QAAQ,CAACqD,MAAM,CAACD,OAAO;YAC/B;QACD;IACD;IAEA,MAAME,OAAOC,OAAe,EAAEC,OAAe,EAAErE,OAAuB,EAAiB;QACtF,IAAIA,SAASuC,QAAQC,SAAS;YAC7B,MAAM,IAAItC,sBAAsB,qBAAqB;QACtD;QAEA,MAAM,CAACoE,SAASC,WAAWC,QAAQ,GAAG,IAAI,CAACrD,cAAc,CAACiD;QAC1D,IAAI,CAACE,WAAW,CAACC,WAAW,MAAM,IAAIrE,sBAAsB,CAAC,kBAAkB,EAAEkE,SAAS,EAAE;QAE5F,MAAMK,eAAeF,UAAU1D,QAAQ,CAAC+C,SAAS,CAAC,CAACc,IAAMA,EAAEpE,IAAI,KAAKkE;QACpED,UAAU1D,QAAQ,CAACqD,MAAM,CAACO,cAAc;QAExC,MAAME,gBAAgB/E,QAAQyE;QAC9B,MAAMO,UAAUjF,SAAS0E;QACzB,MAAMQ,YAAY,IAAI,CAAC3C,sBAAsB,CAACyC;QAE9C,MAAMG,oBAAoBD,UAAUhE,QAAQ,CAAC+C,SAAS,CAAC,CAACc,IAAMA,EAAEpE,IAAI,KAAKsE;QACzE,IAAIE,sBAAsB,CAAC,GAAG;YAC7B,IAAI,CAAC9E,SAASyD,WAAW,MAAM,IAAIvD,sBAAsB,CAAC,oBAAoB,EAAEmE,SAAS,EAAE;YAC3FQ,UAAUhE,QAAQ,CAACqD,MAAM,CAACY,mBAAmB;QAC9C;QAEAR,QAAQhE,IAAI,GAAGsE;QACfN,QAAQ3D,IAAI,GAAG0D;QACfC,QAAQ1D,SAAS,GAAG+D;QACpBL,QAAQvD,KAAK,GAAGC,KAAKC,GAAG;QACxB4D,UAAUhE,QAAQ,CAACwB,IAAI,CAACiC;IACzB;IAEA,MAAMS,KAAKC,OAAe,EAAEC,QAAgB,EAAEjF,OAAqB,EAAiB;QACnF,IAAIA,SAASuC,QAAQC,SAAS;YAC7B,MAAM,IAAItC,sBAAsB,qBAAqB;QACtD;QAEA,MAAM,CAACgF,QAAQ,GAAG,IAAI,CAAC/D,cAAc,CAAC6D;QACtC,IAAI,CAACE,SAAS,MAAM,IAAIhF,sBAAsB,CAAC,kBAAkB,EAAE8E,SAAS,EAAE;QAE9E,MAAMG,YAAY,CAAuBlD,OAAemD,KAAKC,KAAK,CAACD,KAAKE,SAAS,CAACrD;QAClF,MAAMsD,UAAUJ,UAAUD;QAE1B,MAAMP,gBAAgB/E,QAAQqF;QAC9B,MAAML,UAAUjF,SAASsF;QACzB,MAAMJ,YAAY,IAAI,CAAC3C,sBAAsB,CAACyC;QAE9CY,QAAQjF,IAAI,GAAGsE;QACfW,QAAQ5E,IAAI,GAAGsE;QACfM,QAAQ3E,SAAS,GAAG+D;QAEpB,MAAMG,oBAAoBD,UAAUhE,QAAQ,CAAC+C,SAAS,CAAC,CAACc,IAAMA,EAAEpE,IAAI,KAAKsE;QACzE,IAAIE,sBAAsB,CAAC,GAAG;YAC7B,IAAI,CAAC9E,SAASyD,WAAW,MAAM,IAAIvD,sBAAsB,CAAC,oBAAoB,EAAE+E,UAAU,EAAE;YAC5FJ,UAAUhE,QAAQ,CAACiE,kBAAkB,GAAGS;QACzC,OAAO;YACNV,UAAUhE,QAAQ,CAACwB,IAAI,CAACkD;QACzB;IACD;IAEAC,iBAAiB7E,IAAY,EAAEX,OAAiC,EAAY;QAC3E,MAAM,EAAEuC,MAAM,EAAEkD,KAAK,EAAE,GAAGzF,WAAW,CAAC;QAEtC,IAAIuC,QAAQC,SAAS;YACpB,MAAM,IAAItC,sBAAsB,qBAAqB;QACtD;QAEA,MAAM,CAAC+B,KAAK,GAAG,IAAI,CAACd,cAAc,CAACR;QACnC,IAAI,CAACsB,MAAM;YACV,MAAM,IAAI/B,sBAAsB,CAAC,gBAAgB,EAAES,MAAM,EAAE;QAC5D;QACA,IAAIsB,KAAKvB,IAAI,KAAK,QAAQ;YACzB,MAAM,IAAIR,sBAAsB,CAAC,gBAAgB,EAAES,MAAM,EAAE;QAC5D;QAEA,MAAMsC,UAAUG,OAAOC,IAAI,CAAC,aAAapB,OAAOA,KAAKgB,OAAO,GAAG;QAC/D,MAAM,EAAEyC,QAAQ,EAAE,GAAGC,QAAQ;QAE7B,IAAIpC,OAAON;QACX,IAAIwC,OAAO;YACV,MAAMG,QAAQH,MAAMG,KAAK,IAAI;YAC7B,MAAMC,MAAMJ,MAAMI,GAAG,IAAI5C,QAAQxB,MAAM,GAAG;YAC1C8B,OAAON,QAAQ6C,QAAQ,CAACF,OAAOC,MAAM;QACtC;QAEA,MAAME,SAASL,SAASrC,IAAI,CAAC;YAACE;SAAK;QAEnC,IAAIhB,QAAQ;YACXA,OAAOyD,gBAAgB,CAAC,SAAS;gBAChCD,OAAOE,OAAO,CAAC,IAAI/F,sBAAsB,qBAAqB;YAC/D;QACD;QAEA,OAAO6F;IACR;IAEAG,kBAAkBvF,IAAY,EAAEX,OAAkC,EAAY;QAC7E,MAAM,EAAEuC,MAAM,EAAEkB,YAAY,IAAI,EAAE,GAAGzD,WAAW,CAAC;QAEjD,IAAIuC,QAAQC,SAAS;YACpB,MAAM,IAAItC,sBAAsB,qBAAqB;QACtD;QAEA,MAAM,EAAEiG,QAAQ,EAAE,GAAGR,QAAQ;QAC7B,MAAMS,SAAmB,EAAE;QAE3B,MAAMC,OAAO,IAAI;QACjB,MAAMN,SAAS,IAAII,SAAS;YAC3BG,OAAMC,KAAa,EAAErD,QAAwB,EAAEsD,QAAwC;gBACtF,IAAIjE,QAAQC,SAAS;oBACpBgE,SAAS,IAAItG,sBAAsB,qBAAqB;oBACxD;gBACD;gBACAkG,OAAO/D,IAAI,CAACkE;gBACZC;YACD;YACAC,OAAMD,QAAwC;gBAC7C,IAAIjE,QAAQC,SAAS;oBACpBgE,SAAS,IAAItG,sBAAsB,qBAAqB;oBACxD;gBACD;gBAEA,IAAI;oBACH,MAAM+C,UAAUG,OAAOsD,MAAM,CAACN;oBAC9B,MAAMtD,aAAalD,QAAQe;oBAC3B,MAAM+C,WAAW/D,SAASgB;oBAC1B,MAAMoC,SAASsD,KAAKnE,sBAAsB,CAACY;oBAE3C,MAAMa,YAAYZ,OAAOlC,QAAQ,CAAC+C,SAAS,CAAC,CAAC5B,QAAUA,MAAM1B,IAAI,KAAKoD;oBACtE,MAAMG,eAAeF,cAAc,CAAC,IAAIZ,OAAOlC,QAAQ,CAAC8C,UAAU,GAAG;oBAErE,IAAIE,cAAc;wBACjB,IAAI,CAACJ,WAAW;4BACf+C,SAAS,IAAItG,sBAAsB,CAAC,qBAAqB,EAAES,MAAM,EAAE;4BACnE;wBACD;wBACA,IAAIkD,aAAanD,IAAI,KAAK,aAAa;4BACtC8F,SAAS,IAAItG,sBAAsB,CAAC,8BAA8B,EAAES,MAAM,EAAE;4BAC5E;wBACD;wBAEAkD,aAAaZ,OAAO,GAAGA;wBACvBY,aAAa/C,IAAI,GAAGmC,QAAQxB,MAAM;wBAClCoC,aAAa9C,KAAK,GAAGC,KAAKC,GAAG;oBAC9B,OAAO;wBACN,MAAMA,MAAMD,KAAKC,GAAG;wBACpB,MAAM6C,UAAsB;4BAC3BxD,MAAMoD;4BACNhD,MAAM;4BACNC,MAAMA;4BACNC,WAAWkC;4BACXG,SAASA;4BACTnC,MAAMmC,QAAQxB,MAAM;4BACpBV,OAAOE;4BACPC,MAAM,CAAC;wBACR;wBACA6B,OAAOlC,QAAQ,CAACwB,IAAI,CAACyB;oBACtB;oBAEA0C;gBACD,EAAE,OAAOG,OAAO;oBACfH,SAASG,iBAAiBxG,QAAQwG,QAAQ,IAAIzG,sBAAsB,iBAAiB;gBACtF;YACD;QACD;QAEA,IAAIqC,QAAQ;YACXA,OAAOyD,gBAAgB,CAAC,SAAS;gBAChCD,OAAOE,OAAO,CAAC,IAAI/F,sBAAsB,qBAAqB;YAC/D;QACD;QAEA,OAAO6F;IACR;IAEAa,OAAOC,IAAwB,EAAE;QAChC,IAAI5E;QACJ,IAAI,OAAO4E,SAAS,UAAU;YAC7B,CAAC5E,KAAK,GAAG,IAAI,CAACd,cAAc,CAAC0F;QAC9B,OAAO;YACN5E,OAAO4E;QACR;QACA,IAAIC,KAAK7E;QACT,IAAI6E,GAAG7D,OAAO,EAAE;YACf,IAAIyB,IAAIhF,gBAAgB,IAAI,CAACc,KAAK,EAAEsG,IAAI,IAAO,CAAA,CAAC,CAAA;YAChD,IAAI,CAACpC,EAAEqC,GAAG,EAAE;gBACX,IAAIC,OAAOlH,aAAagH,GAAGxG,IAAI,KAAK;gBACpCoE,EAAEqC,GAAG,GAAGE,IAAIC,eAAe,CAAC,IAAIC,KAAK;oBAACL,GAAG7D,OAAO;iBAAC,EAAE;oBAAEmE,MAAMJ;gBAAK;YACjE;YAEA,OAAOtC,EAAEqC,GAAG;QACb;QACA;IACD;IAEAM,qBAAqB1G,IAAY,EAAEX,OAAiC,EAAkB;QACrF,MAAM,EAAEuC,MAAM,EAAEkD,KAAK,EAAE,GAAGzF,WAAW,CAAC;QAEtC,IAAIuC,QAAQC,SAAS;YACpB,MAAM,IAAItC,sBAAsB,qBAAqB;QACtD;QAEA,MAAM,CAAC+B,KAAK,GAAG,IAAI,CAACd,cAAc,CAACR;QACnC,IAAI,CAACsB,MAAM;YACV,MAAM,IAAI/B,sBAAsB,CAAC,gBAAgB,EAAES,MAAM,EAAE;QAC5D;QACA,IAAIsB,KAAKvB,IAAI,KAAK,QAAQ;YACzB,MAAM,IAAIR,sBAAsB,CAAC,gBAAgB,EAAES,MAAM,EAAE;QAC5D;QAEA,MAAMsC,UAAUG,OAAOC,IAAI,CAAC,aAAapB,OAAOA,KAAKgB,OAAO,GAAG;QAE/D,IAAIM,OAAON;QACX,IAAIwC,OAAO;YACV,MAAMG,QAAQH,MAAMG,KAAK,IAAI;YAC7B,MAAMC,MAAMJ,MAAMI,GAAG,IAAI5C,QAAQxB,MAAM,GAAG;YAC1C8B,OAAON,QAAQ6C,QAAQ,CAACF,OAAOC,MAAM;QACtC;QAEA,MAAME,SAAS,IAAIuB,eAAe;YACjC1B,OAAM2B,UAAU;gBACfA,WAAWC,OAAO,CAACjE;gBACnBgE,WAAWE,KAAK;YACjB;QACD;QAEA,IAAIlF,QAAQ;YACXA,OAAOyD,gBAAgB,CAAC,SAAS;gBAChCD,OAAO2B,MAAM,CAAC,IAAIxH,sBAAsB,qBAAqB;YAC9D;QACD;QAEA,OAAO6F;IACR;IAEA4B,qBAAqBhH,IAAY,EAAEX,OAAkC,EAAkB;QACtF,MAAM,EAAEuC,MAAM,EAAEkB,YAAY,IAAI,EAAE,GAAGzD,WAAW,CAAC;QAEjD,IAAIuC,QAAQC,SAAS;YACpB,MAAM,IAAItC,sBAAsB,qBAAqB;QACtD;QAEA,MAAMkG,SAAmB,EAAE;QAE3B,MAAMC,OAAO,IAAI;QACjB,MAAMN,SAAS,IAAI6B,eAAe;YACjCtB,OAAMC,KAAa;gBAClB,IAAIhE,QAAQC,SAAS;oBACpB,MAAM,IAAItC,sBAAsB,qBAAqB;gBACtD;gBACAkG,OAAO/D,IAAI,CAACkE;YACb;YACAkB;gBACC,IAAIlF,QAAQC,SAAS;oBACpB,MAAM,IAAItC,sBAAsB,qBAAqB;gBACtD;gBAEA,MAAM+C,UAAUG,OAAOsD,MAAM,CAACN;gBAC9B,MAAMtD,aAAalD,QAAQe;gBAC3B,MAAM+C,WAAW/D,SAASgB;gBAC1B,MAAMoC,SAASsD,KAAKnE,sBAAsB,CAACY;gBAE3C,MAAMa,YAAYZ,OAAOlC,QAAQ,CAAC+C,SAAS,CAAC,CAAC5B,QAAUA,MAAM1B,IAAI,KAAKoD;gBACtE,MAAMG,eAAeF,cAAc,CAAC,IAAIZ,OAAOlC,QAAQ,CAAC8C,UAAU,GAAG;gBAErE,IAAIE,cAAc;oBACjB,IAAI,CAACJ,WAAW;wBACf,MAAM,IAAIvD,sBAAsB,CAAC,qBAAqB,EAAES,MAAM,EAAE;oBACjE;oBACA,IAAIkD,aAAanD,IAAI,KAAK,aAAa;wBACtC,MAAM,IAAIR,sBAAsB,CAAC,8BAA8B,EAAES,MAAM,EAAE;oBAC1E;oBAEAkD,aAAaZ,OAAO,GAAGA;oBACvBY,aAAa/C,IAAI,GAAGmC,QAAQxB,MAAM;oBAClCoC,aAAa9C,KAAK,GAAGC,KAAKC,GAAG;gBAC9B,OAAO;oBACN,MAAMA,MAAMD,KAAKC,GAAG;oBACpB,MAAM6C,UAAsB;wBAC3BxD,MAAMoD;wBACNhD,MAAM;wBACNC,MAAMA;wBACNC,WAAWkC;wBACXG,SAASA;wBACTnC,MAAMmC,QAAQxB,MAAM;wBACpBV,OAAOE;wBACPC,MAAM,CAAC;oBACR;oBACA6B,OAAOlC,QAAQ,CAACwB,IAAI,CAACyB;gBACtB;YACD;QACD;QAEA,IAAIvB,QAAQ;YACXA,OAAOyD,gBAAgB,CAAC,SAAS;gBAChCD,OAAO8B,KAAK,CAAC,IAAI3H,sBAAsB,qBAAqB;YAC7D;QACD;QAEA,OAAO6F;IACR;AACD"}
|
|
1
|
+
{"version":3,"sources":["../../src/fs/createMemoryFileSystem.ts"],"sourcesContent":["import type { Readable, Writable } from 'node:stream';\nimport { computeIfAbsent } from '@wener/utils';\nimport { basename, dirname, normalize } from 'pathe';\nimport { FileSystemError } from './FileSystemError';\nimport { findMimeType } from './findMimeType';\nimport type {\n\tCopyOptions,\n\tCreateReadStreamOptions,\n\tCreateWriteStreamOptions,\n\tIFileStat,\n\tIFileSystem,\n\tMkdirOptions,\n\tReadFileOptions,\n\tRenameOptions,\n\tRmOptions,\n\tWriteFileOptions,\n} from './IFileSystem';\n\ntype MemoryNode = MemoryFile | MemoryDirectory;\n\ntype MemoryFile = IFileStat & {\n\tkind: 'file';\n\tcontent: string | Buffer;\n};\n\ntype MemoryDirectory = IFileStat & {\n\tkind: 'directory';\n\tchildren: MemoryNode[];\n};\n\nexport function createMemoryFileSystem(options: { root?: MemoryDirectory } = {}): IFileSystem {\n\treturn new MemFS(options);\n}\n\nclass MemoryFileSystemError extends FileSystemError {\n\tconstructor(message: string, code: string) {\n\t\tsuper(message, code);\n\t\tthis.name = 'MemoryFileSystemError';\n\t}\n}\n\ntype Cache = {\n\turl?: string;\n};\n\nclass MemFS implements IFileSystem {\n\tprivate readonly root: MemoryDirectory;\n\n\tprivate readonly cache = new WeakMap<MemoryNode, Cache>();\n\n\tconstructor({\n\t\troot,\n\t}: {\n\t\troot?: MemoryDirectory;\n\t} = {}) {\n\t\tthis.root = root || {\n\t\t\tname: '',\n\t\t\tkind: 'directory',\n\t\t\tpath: '/',\n\t\t\tdirectory: '',\n\t\t\tchildren: [],\n\t\t\tsize: 0,\n\t\t\tmtime: Date.now(),\n\t\t\tmeta: {},\n\t\t};\n\t}\n\n\t/**\n\t * 核心辅助方法:通过路径查找节点\n\t * @returns A tuple: [foundNode, parentNode, finalName]\n\t */\n\tprivate _getNodeByPath(path: string): [MemoryNode | null, MemoryDirectory | null, string] {\n\t\tif (!path || typeof path !== 'string') {\n\t\t\tthrow new MemoryFileSystemError('Invalid path: path must be a non-empty string', 'EINVAL');\n\t\t}\n\n\t\tconst normalized = normalize(path);\n\t\tif (normalized === '/') {\n\t\t\t// the parent of root is itself\n\t\t\treturn [this.root, this.root, ''];\n\t\t}\n\n\t\tconst parts = normalized.split('/').filter((p) => p);\n\t\tif (parts.length === 0) {\n\t\t\treturn [this.root, this.root, ''];\n\t\t}\n\n\t\tconst finalName = parts.pop()!;\n\n\t\tlet current: MemoryDirectory = this.root;\n\t\tfor (const part of parts) {\n\t\t\tif (!part) continue; // skip empty parts\n\n\t\t\tconst found = current.children.find((child) => child.name === part);\n\t\t\tif (!found || found.kind !== 'directory') {\n\t\t\t\treturn [null, null, finalName];\n\t\t\t}\n\t\t\tcurrent = found;\n\t\t}\n\n\t\tconst node = current.children.find((child) => child.name === finalName) ?? null;\n\t\treturn [node, current, finalName];\n\t}\n\n\t/**\n\t * 核心辅助方法:查找或创建目录\n\t */\n\tprivate _findOrCreateDirectory(path: string): MemoryDirectory {\n\t\tif (!path || typeof path !== 'string') {\n\t\t\tthrow new MemoryFileSystemError('Invalid path: path must be a non-empty string', 'EINVAL');\n\t\t}\n\n\t\tconst normalized = normalize(path);\n\t\tif (normalized === '/') return this.root;\n\n\t\tconst parts = normalized.split('/').filter((p) => p);\n\t\tif (parts.length === 0) return this.root;\n\n\t\tlet current: MemoryDirectory = this.root;\n\t\tlet currentPath = '';\n\n\t\tfor (const part of parts) {\n\t\t\tif (!part) continue; // skip empty parts\n\n\t\t\tcurrentPath = `${currentPath}/${part}`;\n\t\t\tlet found = current.children.find((child) => child.name === part);\n\t\t\tif (!found) {\n\t\t\t\tconst now = Date.now();\n\t\t\t\tconst newDir: MemoryDirectory = {\n\t\t\t\t\tname: part,\n\t\t\t\t\tkind: 'directory',\n\t\t\t\t\tpath: currentPath,\n\t\t\t\t\tdirectory: dirname(currentPath),\n\t\t\t\t\tchildren: [],\n\t\t\t\t\tsize: 0,\n\t\t\t\t\tmtime: now,\n\t\t\t\t\tmeta: {},\n\t\t\t\t};\n\t\t\t\tcurrent.children.push(newDir);\n\t\t\t\tcurrent = newDir;\n\t\t\t} else if (found.kind !== 'directory') {\n\t\t\t\tthrow new MemoryFileSystemError(`Path conflict: ${currentPath} is a file`, 'ENOTDIR');\n\t\t\t} else {\n\t\t\t\tcurrent = found;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t}\n\n\tasync stat(path: string, options?: { signal?: AbortSignal }): Promise<IFileStat> {\n\t\tif (options?.signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst [node] = this._getNodeByPath(path);\n\t\tif (!node) {\n\t\t\tthrow new MemoryFileSystemError(`File not found: ${path}`, 'ENOENT');\n\t\t}\n\t\treturn { ...node };\n\t}\n\n\tasync exists(path: string): Promise<boolean> {\n\t\tconst [node] = this._getNodeByPath(path);\n\t\treturn !!node;\n\t}\n\n\tasync readdir(path: string, options?: { signal?: AbortSignal }): Promise<IFileStat[]> {\n\t\tif (options?.signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst [node] = this._getNodeByPath(path);\n\t\tif (!node) {\n\t\t\tthrow new MemoryFileSystemError(`Directory not found: ${path}`, 'ENOENT');\n\t\t}\n\t\tif (node.kind !== 'directory') {\n\t\t\tthrow new MemoryFileSystemError(`Not a directory: ${path}`, 'ENOTDIR');\n\t\t}\n\t\t// 返回副本\n\t\treturn node.children.map((child) => ({ ...child }));\n\t}\n\n\tasync mkdir(path: string, options?: MkdirOptions): Promise<void> {\n\t\tif (options?.signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst [node] = this._getNodeByPath(path);\n\t\tif (node) {\n\t\t\tif (node.kind === 'file') throw new MemoryFileSystemError(`File already exists: ${path}`, 'EEXIST');\n\t\t\treturn; // 目录已存在\n\t\t}\n\n\t\tif (options?.recursive) {\n\t\t\tthis._findOrCreateDirectory(path);\n\t\t} else {\n\t\t\tconst parentPath = dirname(path);\n\t\t\tconst [, parent] = this._getNodeByPath(parentPath);\n\t\t\tif (!parent) {\n\t\t\t\tthrow new MemoryFileSystemError(`Parent directory does not exist: ${parentPath}`, 'ENOENT');\n\t\t\t}\n\t\t\tthis._findOrCreateDirectory(path);\n\t\t}\n\t}\n\n\treadFile(path: string, options?: ReadFileOptions & { encoding: 'text' }): Promise<string>;\n\treadFile(path: string, options?: ReadFileOptions): Promise<Uint8Array>;\n\tasync readFile(path: string, options?: ReadFileOptions): Promise<string | Uint8Array> {\n\t\tif (options?.signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst [node] = this._getNodeByPath(path);\n\t\tif (!node) {\n\t\t\tthrow new MemoryFileSystemError(`File not found: ${path}`, 'ENOENT');\n\t\t}\n\t\tif (node.kind !== 'file') {\n\t\t\tthrow new MemoryFileSystemError(`Is a directory: ${path}`, 'EISDIR');\n\t\t}\n\n\t\tconst content = 'content' in node ? node.content : '';\n\t\treturn options?.encoding === 'text' ? content.toString() : Buffer.from(content);\n\t}\n\n\tasync writeFile(path: string, data: string | Buffer, options: WriteFileOptions = {}): Promise<void> {\n\t\tif (options?.signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tif (!path || typeof path !== 'string') {\n\t\t\tthrow new MemoryFileSystemError('Invalid path: path must be a non-empty string', 'EINVAL');\n\t\t}\n\n\t\tif (data === null || data === undefined) {\n\t\t\tthrow new MemoryFileSystemError('Invalid data: data cannot be null or undefined', 'EINVAL');\n\t\t}\n\n\t\tconst { overwrite = true } = options;\n\t\tconst parentPath = dirname(path);\n\t\tconst filename = basename(path);\n\n\t\tif (!filename) {\n\t\t\tthrow new MemoryFileSystemError('Invalid path: filename cannot be empty', 'EINVAL');\n\t\t}\n\n\t\tconst parent = this._findOrCreateDirectory(parentPath);\n\t\tconst nodeIndex = parent.children.findIndex((child) => child.name === filename);\n\t\tconst existingNode = nodeIndex !== -1 ? parent.children[nodeIndex] : null;\n\n\t\tif (existingNode) {\n\t\t\tif (!overwrite) throw new MemoryFileSystemError(`File already exists: ${path}`, 'EEXIST');\n\t\t\tif (existingNode.kind === 'directory')\n\t\t\t\tthrow new MemoryFileSystemError(`Cannot overwrite a directory: ${path}`, 'EISDIR');\n\n\t\t\t// 更新文件\n\t\t\texistingNode.content = data;\n\t\t\texistingNode.size = data.length;\n\t\t\texistingNode.mtime = Date.now();\n\t\t} else {\n\t\t\t// 创建新文件\n\t\t\tconst now = Date.now();\n\t\t\tconst newFile: MemoryFile = {\n\t\t\t\tname: filename,\n\t\t\t\tkind: 'file',\n\t\t\t\tpath: path,\n\t\t\t\tdirectory: parentPath,\n\t\t\t\tcontent: data,\n\t\t\t\tsize: data.length,\n\t\t\t\tmtime: now,\n\t\t\t\tmeta: {},\n\t\t\t};\n\t\t\tparent.children.push(newFile);\n\t\t}\n\t}\n\n\tasync rm(path: string, options: RmOptions = {}): Promise<void> {\n\t\tif (options?.signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst { recursive = false, force = false } = options;\n\t\tconst [node, parent] = this._getNodeByPath(path);\n\n\t\tif (!node) {\n\t\t\tif (force) return;\n\t\t\tthrow new MemoryFileSystemError(`File not found: ${path}`, 'ENOENT');\n\t\t}\n\n\t\tif (node.kind === 'directory' && node.children.length > 0 && !recursive) {\n\t\t\tthrow new MemoryFileSystemError(`Directory not empty: ${path}`, 'ENOTEMPTY');\n\t\t}\n\n\t\tif (parent) {\n\t\t\tconst index = parent.children.findIndex((child) => child.name === node.name);\n\t\t\tif (index !== -1) {\n\t\t\t\tparent.children.splice(index, 1);\n\t\t\t}\n\t\t}\n\t}\n\n\tasync rename(oldPath: string, newPath: string, options?: RenameOptions): Promise<void> {\n\t\tif (options?.signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst [oldNode, oldParent, oldName] = this._getNodeByPath(oldPath);\n\t\tif (!oldNode || !oldParent) throw new MemoryFileSystemError(`Source not found: ${oldPath}`, 'ENOENT');\n\n\t\tconst oldNodeIndex = oldParent.children.findIndex((c) => c.name === oldName);\n\t\toldParent.children.splice(oldNodeIndex, 1);\n\n\t\tconst newParentPath = dirname(newPath);\n\t\tconst newName = basename(newPath);\n\t\tconst newParent = this._findOrCreateDirectory(newParentPath);\n\n\t\tconst existingNodeIndex = newParent.children.findIndex((c) => c.name === newName);\n\t\tif (existingNodeIndex !== -1) {\n\t\t\tif (!options?.overwrite) throw new MemoryFileSystemError(`Destination exists: ${newPath}`, 'EEXIST');\n\t\t\tnewParent.children.splice(existingNodeIndex, 1);\n\t\t}\n\n\t\toldNode.name = newName;\n\t\toldNode.path = newPath;\n\t\toldNode.directory = newParentPath;\n\t\toldNode.mtime = Date.now();\n\t\tnewParent.children.push(oldNode);\n\t}\n\n\tasync copy(srcPath: string, destPath: string, options?: CopyOptions): Promise<void> {\n\t\tif (options?.signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst [srcNode] = this._getNodeByPath(srcPath);\n\t\tif (!srcNode) throw new MemoryFileSystemError(`Source not found: ${srcPath}`, 'ENOENT');\n\n\t\tconst deepClone = <T extends MemoryNode>(node: T): T => JSON.parse(JSON.stringify(node));\n\t\tconst newNode = deepClone(srcNode);\n\n\t\tconst newParentPath = dirname(destPath);\n\t\tconst newName = basename(destPath);\n\t\tconst newParent = this._findOrCreateDirectory(newParentPath);\n\n\t\tnewNode.name = newName;\n\t\tnewNode.path = destPath;\n\t\tnewNode.directory = newParentPath;\n\n\t\tconst existingNodeIndex = newParent.children.findIndex((c) => c.name === newName);\n\t\tif (existingNodeIndex !== -1) {\n\t\t\tif (!options?.overwrite) throw new MemoryFileSystemError(`Destination exists: ${destPath}`, 'EEXIST');\n\t\t\tnewParent.children[existingNodeIndex] = newNode;\n\t\t} else {\n\t\t\tnewParent.children.push(newNode);\n\t\t}\n\t}\n\n\tcreateReadStream(path: string, options?: CreateReadStreamOptions): Readable {\n\t\tconst { signal, range } = options || {};\n\n\t\tif (signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst [node] = this._getNodeByPath(path);\n\t\tif (!node) {\n\t\t\tthrow new MemoryFileSystemError(`File not found: ${path}`, 'ENOENT');\n\t\t}\n\t\tif (node.kind !== 'file') {\n\t\t\tthrow new MemoryFileSystemError(`Is a directory: ${path}`, 'EISDIR');\n\t\t}\n\n\t\tconst content = Buffer.from('content' in node ? node.content : '');\n\t\tconst { Readable } = require('node:stream');\n\n\t\tlet data = content;\n\t\tif (range) {\n\t\t\tconst start = range.start || 0;\n\t\t\tconst end = range.end || content.length - 1;\n\t\t\tdata = content.subarray(start, end + 1);\n\t\t}\n\n\t\tconst stream = Readable.from([data]);\n\n\t\tif (signal) {\n\t\t\tsignal.addEventListener('abort', () => {\n\t\t\t\tstream.destroy(new MemoryFileSystemError('Operation aborted', 'ABORT_ERR'));\n\t\t\t});\n\t\t}\n\n\t\treturn stream;\n\t}\n\n\tcreateWriteStream(path: string, options?: CreateWriteStreamOptions): Writable {\n\t\tconst { signal, overwrite = true } = options || {};\n\n\t\tif (signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst { Writable } = require('node:stream');\n\t\tconst chunks: Buffer[] = [];\n\n\t\tconst self = this;\n\t\tconst stream = new Writable({\n\t\t\twrite(chunk: Buffer, _encoding: BufferEncoding, callback: (error?: Error | null) => void) {\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tcallback(new MemoryFileSystemError('Operation aborted', 'ABORT_ERR'));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tchunks.push(chunk);\n\t\t\t\tcallback();\n\t\t\t},\n\t\t\tfinal(callback: (error?: Error | null) => void) {\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tcallback(new MemoryFileSystemError('Operation aborted', 'ABORT_ERR'));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst content = Buffer.concat(chunks);\n\t\t\t\t\tconst parentPath = dirname(path);\n\t\t\t\t\tconst filename = basename(path);\n\t\t\t\t\tconst parent = self._findOrCreateDirectory(parentPath);\n\n\t\t\t\t\tconst nodeIndex = parent.children.findIndex((child) => child.name === filename);\n\t\t\t\t\tconst existingNode = nodeIndex !== -1 ? parent.children[nodeIndex] : null;\n\n\t\t\t\t\tif (existingNode) {\n\t\t\t\t\t\tif (!overwrite) {\n\t\t\t\t\t\t\tcallback(new MemoryFileSystemError(`File already exists: ${path}`, 'EEXIST'));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (existingNode.kind === 'directory') {\n\t\t\t\t\t\t\tcallback(new MemoryFileSystemError(`Cannot overwrite a directory: ${path}`, 'EISDIR'));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\texistingNode.content = content;\n\t\t\t\t\t\texistingNode.size = content.length;\n\t\t\t\t\t\texistingNode.mtime = Date.now();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst now = Date.now();\n\t\t\t\t\t\tconst newFile: MemoryFile = {\n\t\t\t\t\t\t\tname: filename,\n\t\t\t\t\t\t\tkind: 'file',\n\t\t\t\t\t\t\tpath: path,\n\t\t\t\t\t\t\tdirectory: parentPath,\n\t\t\t\t\t\t\tcontent: content,\n\t\t\t\t\t\t\tsize: content.length,\n\t\t\t\t\t\t\tmtime: now,\n\t\t\t\t\t\t\tmeta: {},\n\t\t\t\t\t\t};\n\t\t\t\t\t\tparent.children.push(newFile);\n\t\t\t\t\t}\n\n\t\t\t\t\tcallback();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tcallback(error instanceof Error ? error : new MemoryFileSystemError('Unknown error', 'UNKNOWN'));\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\n\t\tif (signal) {\n\t\t\tsignal.addEventListener('abort', () => {\n\t\t\t\tstream.destroy(new MemoryFileSystemError('Operation aborted', 'ABORT_ERR'));\n\t\t\t});\n\t\t}\n\n\t\treturn stream;\n\t}\n\n\tgetUrl(file: IFileStat | string) {\n\t\tlet node: IFileStat | null;\n\t\tif (typeof file === 'string') {\n\t\t\t[node] = this._getNodeByPath(file);\n\t\t} else {\n\t\t\tnode = file;\n\t\t}\n\t\tlet mf = node as MemoryFile;\n\t\tif (mf.content) {\n\t\t\tlet c = computeIfAbsent(this.cache, mf, () => ({}) as Cache);\n\t\t\tif (!c.url) {\n\t\t\t\tlet mime = findMimeType(mf.name) || 'application/octet-stream';\n\t\t\t\t// Convert Buffer to Uint8Array for Blob compatibility with TypeScript 5.x strict typing\n\t\t\t\tconst blobPart = typeof mf.content === 'string' ? mf.content : new Uint8Array(mf.content);\n\t\t\t\tc.url = URL.createObjectURL(new Blob([blobPart], { type: mime }));\n\t\t\t}\n\n\t\t\treturn c.url;\n\t\t}\n\t\treturn;\n\t}\n\n\tcreateReadableStream(path: string, options?: CreateReadStreamOptions): ReadableStream {\n\t\tconst { signal, range } = options || {};\n\n\t\tif (signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst [node] = this._getNodeByPath(path);\n\t\tif (!node) {\n\t\t\tthrow new MemoryFileSystemError(`File not found: ${path}`, 'ENOENT');\n\t\t}\n\t\tif (node.kind !== 'file') {\n\t\t\tthrow new MemoryFileSystemError(`Is a directory: ${path}`, 'EISDIR');\n\t\t}\n\n\t\tconst content = Buffer.from('content' in node ? node.content : '');\n\n\t\tlet data = content;\n\t\tif (range) {\n\t\t\tconst start = range.start || 0;\n\t\t\tconst end = range.end || content.length - 1;\n\t\t\tdata = content.subarray(start, end + 1);\n\t\t}\n\n\t\tconst stream = new ReadableStream({\n\t\t\tstart(controller) {\n\t\t\t\tcontroller.enqueue(data);\n\t\t\t\tcontroller.close();\n\t\t\t},\n\t\t});\n\n\t\tif (signal) {\n\t\t\tsignal.addEventListener('abort', () => {\n\t\t\t\tstream.cancel(new MemoryFileSystemError('Operation aborted', 'ABORT_ERR'));\n\t\t\t});\n\t\t}\n\n\t\treturn stream;\n\t}\n\n\tcreateWritableStream(path: string, options?: CreateWriteStreamOptions): WritableStream {\n\t\tconst { signal, overwrite = true } = options || {};\n\n\t\tif (signal?.aborted) {\n\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t}\n\n\t\tconst chunks: Buffer[] = [];\n\n\t\tconst self = this;\n\t\tconst stream = new WritableStream({\n\t\t\twrite(chunk: Buffer) {\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t\t\t}\n\t\t\t\tchunks.push(chunk);\n\t\t\t},\n\t\t\tclose() {\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tthrow new MemoryFileSystemError('Operation aborted', 'ABORT_ERR');\n\t\t\t\t}\n\n\t\t\t\tconst content = Buffer.concat(chunks);\n\t\t\t\tconst parentPath = dirname(path);\n\t\t\t\tconst filename = basename(path);\n\t\t\t\tconst parent = self._findOrCreateDirectory(parentPath);\n\n\t\t\t\tconst nodeIndex = parent.children.findIndex((child) => child.name === filename);\n\t\t\t\tconst existingNode = nodeIndex !== -1 ? parent.children[nodeIndex] : null;\n\n\t\t\t\tif (existingNode) {\n\t\t\t\t\tif (!overwrite) {\n\t\t\t\t\t\tthrow new MemoryFileSystemError(`File already exists: ${path}`, 'EEXIST');\n\t\t\t\t\t}\n\t\t\t\t\tif (existingNode.kind === 'directory') {\n\t\t\t\t\t\tthrow new MemoryFileSystemError(`Cannot overwrite a directory: ${path}`, 'EISDIR');\n\t\t\t\t\t}\n\n\t\t\t\t\texistingNode.content = content;\n\t\t\t\t\texistingNode.size = content.length;\n\t\t\t\t\texistingNode.mtime = Date.now();\n\t\t\t\t} else {\n\t\t\t\t\tconst now = Date.now();\n\t\t\t\t\tconst newFile: MemoryFile = {\n\t\t\t\t\t\tname: filename,\n\t\t\t\t\t\tkind: 'file',\n\t\t\t\t\t\tpath: path,\n\t\t\t\t\t\tdirectory: parentPath,\n\t\t\t\t\t\tcontent: content,\n\t\t\t\t\t\tsize: content.length,\n\t\t\t\t\t\tmtime: now,\n\t\t\t\t\t\tmeta: {},\n\t\t\t\t\t};\n\t\t\t\t\tparent.children.push(newFile);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\n\t\tif (signal) {\n\t\t\tsignal.addEventListener('abort', () => {\n\t\t\t\tstream.abort(new MemoryFileSystemError('Operation aborted', 'ABORT_ERR'));\n\t\t\t});\n\t\t}\n\n\t\treturn stream;\n\t}\n}\n"],"names":["computeIfAbsent","basename","dirname","normalize","FileSystemError","findMimeType","createMemoryFileSystem","options","MemFS","MemoryFileSystemError","message","code","name","root","cache","WeakMap","kind","path","directory","children","size","mtime","Date","now","meta","_getNodeByPath","normalized","parts","split","filter","p","length","finalName","pop","current","part","found","find","child","node","_findOrCreateDirectory","currentPath","newDir","push","stat","signal","aborted","exists","readdir","map","mkdir","recursive","parentPath","parent","readFile","content","encoding","toString","Buffer","from","writeFile","data","undefined","overwrite","filename","nodeIndex","findIndex","existingNode","newFile","rm","force","index","splice","rename","oldPath","newPath","oldNode","oldParent","oldName","oldNodeIndex","c","newParentPath","newName","newParent","existingNodeIndex","copy","srcPath","destPath","srcNode","deepClone","JSON","parse","stringify","newNode","createReadStream","range","Readable","require","start","end","subarray","stream","addEventListener","destroy","createWriteStream","Writable","chunks","self","write","chunk","_encoding","callback","final","concat","error","Error","getUrl","file","mf","url","mime","blobPart","Uint8Array","URL","createObjectURL","Blob","type","createReadableStream","ReadableStream","controller","enqueue","close","cancel","createWritableStream","WritableStream","abort"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/fs/createSandboxFileSystem.ts"],"sourcesContent":["import { join, normalize, relative, sep } from 'pathe';\nimport type { IFileStat,
|
|
1
|
+
{"version":3,"sources":["../../src/fs/createSandboxFileSystem.ts"],"sourcesContent":["import { join, normalize, relative, sep } from 'pathe';\nimport type { IFileStat, IServerFileSystem, ReadFileOptions } from './IFileSystem';\nimport { getPath } from './utils';\n\nclass SandboxSecurityError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = 'SandboxSecurityError';\n\t}\n}\n\nexport function createSandboxFileSystem(\n\tfs: IServerFileSystem,\n\tbasePath: string,\n): IServerFileSystem & {\n\tfs: IServerFileSystem;\n\tbasePath: string;\n} {\n\treturn new SandboxFS(fs, basePath);\n}\n\nclass SandboxFS implements IServerFileSystem {\n\tfs: IServerFileSystem;\n\tbasePath: string;\n\n\tconstructor(fs: IServerFileSystem, basePath: string) {\n\t\tthis.fs = fs;\n\t\tthis.basePath = normalize(basePath);\n\t}\n\n\tprivate _resolvePath(userPath: string): string {\n\t\tconst fullPath = join(this.basePath, userPath);\n\n\t\tconst normalizedFullPath = normalize(fullPath);\n\n\t\tconst rel = relative(this.basePath, normalizedFullPath);\n\t\tif (rel.startsWith('..') || rel === '..') {\n\t\t\tthrow new SandboxSecurityError(`Path traversal attempt detected: ${userPath}`);\n\t\t}\n\t\treturn normalizedFullPath;\n\t}\n\n\tprivate _stripPath(fullPath: string): string {\n\t\tconst relPath = relative(this.basePath, fullPath);\n\t\t// 保证返回的是一个以 '/' 开头的绝对路径(在沙箱内)\n\t\treturn sep + relPath.split(sep).join('/');\n\t}\n\n\tprivate _processStat(stat: IFileStat): IFileStat {\n\t\tstat.path = this._stripPath(stat.path);\n\t\tstat.directory = this._stripPath(stat.directory);\n\t\treturn stat;\n\t}\n\n\tasync stat(path: string, options?: any): Promise<IFileStat> {\n\t\tconst fullPath = this._resolvePath(path);\n\t\tconst result = await this.fs.stat(fullPath, options);\n\t\treturn this._processStat(result);\n\t}\n\n\tasync readdir(dir: string, options?: any): Promise<IFileStat[]> {\n\t\tconst fullPath = this._resolvePath(dir);\n\t\tconst results = await this.fs.readdir(fullPath, options);\n\t\treturn results.map((stat) => this._processStat(stat));\n\t}\n\n\tasync exists(path: string): Promise<boolean> {\n\t\ttry {\n\t\t\tconst fullPath = this._resolvePath(path);\n\t\t\treturn await this.fs.exists(fullPath);\n\t\t} catch (e) {\n\t\t\tif (e instanceof SandboxSecurityError) {\n\t\t\t\treturn false; // 越界访问视为不存在\n\t\t\t}\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tmkdir(path: string, options?: any): Promise<void> {\n\t\tconst fullPath = this._resolvePath(path);\n\t\treturn this.fs.mkdir(fullPath, options);\n\t}\n\n\treadFile(path: string, options?: ReadFileOptions & { encoding: 'text' }): Promise<string>;\n\treadFile(path: string, options?: ReadFileOptions): Promise<Uint8Array>;\n\treadFile(path: string, options?: ReadFileOptions): Promise<string | Uint8Array> {\n\t\tconst fullPath = this._resolvePath(path);\n\t\treturn this.fs.readFile(fullPath, options);\n\t}\n\n\twriteFile(path: string, data: any, options?: any): Promise<void> {\n\t\tconst fullPath = this._resolvePath(path);\n\t\treturn this.fs.writeFile(fullPath, data, options);\n\t}\n\n\trm(path: string, options?: any): Promise<void> {\n\t\tconst fullPath = this._resolvePath(path);\n\t\treturn this.fs.rm(fullPath, options);\n\t}\n\n\trename(oldPath: string, newPath: string, options?: any): Promise<void> {\n\t\tconst fullOldPath = this._resolvePath(oldPath);\n\t\tconst fullNewPath = this._resolvePath(newPath);\n\t\treturn this.fs.rename(fullOldPath, fullNewPath, options);\n\t}\n\n\tcopy(src: string, dest: string, options?: any): Promise<void> {\n\t\tconst fullSrc = this._resolvePath(src);\n\t\tconst fullDest = this._resolvePath(dest);\n\t\treturn this.fs.copy(fullSrc, fullDest, options);\n\t}\n\n\tcreateReadStream(path: string, options?: any): any {\n\t\tconst fullPath = this._resolvePath(path);\n\t\tif (!this.fs.createReadStream) {\n\t\t\tthrow new Error('Underlying filesystem does not support createReadStream');\n\t\t}\n\t\treturn this.fs.createReadStream(fullPath, options);\n\t}\n\n\tcreateWriteStream(path: string, options?: any): any {\n\t\tconst fullPath = this._resolvePath(path);\n\t\tif (!this.fs.createWriteStream) {\n\t\t\tthrow new Error('Underlying filesystem does not support createWriteStream');\n\t\t}\n\t\treturn this.fs.createWriteStream(fullPath, options);\n\t}\n\n\tgetUrl(file: IFileStat, options?: any): string | undefined {\n\t\tlet path = this._resolvePath(getPath(file.path));\n\t\tif (this.fs.getUrl) {\n\t\t\treturn this.fs.getUrl(path, options);\n\t\t}\n\t\treturn;\n\t}\n}\n"],"names":["join","normalize","relative","sep","getPath","SandboxSecurityError","Error","message","name","createSandboxFileSystem","fs","basePath","SandboxFS","_resolvePath","userPath","fullPath","normalizedFullPath","rel","startsWith","_stripPath","relPath","split","_processStat","stat","path","directory","options","result","readdir","dir","results","map","exists","e","mkdir","readFile","writeFile","data","rm","rename","oldPath","newPath","fullOldPath","fullNewPath","copy","src","dest","fullSrc","fullDest","createReadStream","createWriteStream","getUrl","file"],"mappings":"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"}
|
|
@@ -22,10 +22,10 @@ let WebdavFS = class WebdavFS {
|
|
|
22
22
|
const { filename: path, basename, lastmod, type: kind, etag, size, mime } = input;
|
|
23
23
|
let meta = {};
|
|
24
24
|
if (etag) {
|
|
25
|
-
meta
|
|
25
|
+
meta.etag = etag;
|
|
26
26
|
}
|
|
27
27
|
if (mime) {
|
|
28
|
-
meta
|
|
28
|
+
meta.mime = mime;
|
|
29
29
|
}
|
|
30
30
|
return {
|
|
31
31
|
directory: path.substring(0, path.lastIndexOf('/')) || '/',
|
|
@@ -38,7 +38,8 @@ let WebdavFS = class WebdavFS {
|
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
getData(input) {
|
|
41
|
-
if (input && typeof input === 'object' && 'data' in input && '
|
|
41
|
+
if (input && typeof input === 'object' && 'data' in input && // 'headers' in input &&
|
|
42
|
+
'status' in input && typeof input.status === 'number') {
|
|
42
43
|
return input.data;
|
|
43
44
|
}
|
|
44
45
|
return input;
|
|
@@ -105,9 +106,25 @@ let WebdavFS = class WebdavFS {
|
|
|
105
106
|
return this.getData(res);
|
|
106
107
|
}
|
|
107
108
|
async writeFile(path, data, options = {}) {
|
|
108
|
-
|
|
109
|
+
// Convert web ReadableStream to something WebDAV client can handle
|
|
110
|
+
let webdavData = data;
|
|
111
|
+
if (data instanceof ReadableStream) {
|
|
112
|
+
// Convert web ReadableStream to Buffer
|
|
113
|
+
const reader = data.getReader();
|
|
114
|
+
const chunks = [];
|
|
115
|
+
while(true){
|
|
116
|
+
const { done, value } = await reader.read();
|
|
117
|
+
if (done) break;
|
|
118
|
+
if (value) chunks.push(value);
|
|
119
|
+
}
|
|
120
|
+
webdavData = Buffer.concat(chunks);
|
|
121
|
+
} else if (ArrayBuffer.isView(data) && !(data instanceof Buffer)) {
|
|
122
|
+
// Convert ArrayBufferView to Buffer
|
|
123
|
+
webdavData = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
|
124
|
+
}
|
|
125
|
+
await this.client.putFileContents(path, webdavData, options);
|
|
109
126
|
}
|
|
110
|
-
async rm(path, { signal, force, recursive } = {}) {
|
|
127
|
+
async rm(path, { signal: _signal, force, recursive: _recursive } = {}) {
|
|
111
128
|
try {
|
|
112
129
|
await this.client.deleteFile(path);
|
|
113
130
|
} catch (e) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/fs/createWebDavFileSystem.ts"],"sourcesContent":["import type { Readable, Writable } from 'node:stream';\nimport { maybeFunction, type MaybeFunction } from '@wener/utils';\nimport type { FileStat, GetDirectoryContentsOptions, ResponseDataDetailed, WebDAVClient } from 'webdav';\nimport type {\n\tIFileStat,\n\tIFileSystem,\n\tMkdirOptions,\n\tReaddirOptions,\n\tReadFileOptions,\n\tRmOptions,\n\tStatOptions,\n} from './IFileSystem';\n\nexport function createWebDavFileSystem({ client }: { client: MaybeFunction<WebDAVClient> }): IFileSystem {\n\tlet fs = new WebdavFS({ client });\n\treturn fs;\n}\n\nclass WebdavFS implements IFileSystem {\n\t_client: MaybeFunction<WebDAVClient>;\n\n\tconstructor({\n\t\tclient = () => {\n\t\t\tthrow new Error('WebdavFS client not initialized');\n\t\t},\n\t}: {\n\t\tclient?: MaybeFunction<WebDAVClient>;\n\t}) {\n\t\tthis._client = client;\n\t}\n\n\tset client(client: MaybeFunction<WebDAVClient>) {\n\t\tthis._client = client;\n\t}\n\n\tget client(): WebDAVClient {\n\t\treturn maybeFunction(this._client);\n\t}\n\n\tprivate toEntry(input: FileStat): IFileStat {\n\t\tconst { filename: path, basename, lastmod, type: kind, etag, size, mime } = input;\n\t\tlet meta: Record<string, any> = {};\n\t\tif (etag) {\n\t\t\tmeta['etag'] = etag;\n\t\t}\n\t\tif (mime) {\n\t\t\tmeta['mime'] = mime;\n\t\t}\n\t\treturn {\n\t\t\tdirectory: path.substring(0, path.lastIndexOf('/')) || '/',\n\t\t\tpath,\n\t\t\tname: basename,\n\t\t\tmtime: +new Date(lastmod),\n\t\t\tkind,\n\t\t\tmeta,\n\t\t\tsize,\n\t\t};\n\t}\n\n\tprivate getData<T>(input: ResponseDataDetailed<T> | T): T {\n\t\tif (\n\t\t\tinput\n\t\t\t&& typeof input === 'object'\n\t\t\t&& 'data' in input\n\t\t\t// 'headers' in input &&\n\t\t\t&& 'status' in input\n\t\t\t&& typeof input.status === 'number'\n\t\t) {\n\t\t\treturn input.data;\n\t\t}\n\t\treturn input as T;\n\t}\n\n\tasync readdir(\n\t\tpath: string,\n\t\t{ glob, recursive, depth, kind, hidden, signal }: ReaddirOptions = {},\n\t): Promise<IFileStat[]> {\n\t\t// webdav depth 只支持 0,1\n\t\tlet o: GetDirectoryContentsOptions = {};\n\t\tif (recursive) {\n\t\t\to.deep = true;\n\t\t}\n\t\tlet res = await this.client.getDirectoryContents(path, {\n\t\t\tdeep: recursive,\n\t\t\tsignal,\n\t\t});\n\n\t\tlet out: FileStat[] = this.getData(res);\n\n\t\tif (!recursive && typeof depth === 'number' && depth >= 2) {\n\t\t\tlet l = depth;\n\t\t\tlet cur = out;\n\t\t\twhile (l-- > 1) {\n\t\t\t\tlet sub = (\n\t\t\t\t\tawait Promise.all(\n\t\t\t\t\t\tcur.map(async (v) => {\n\t\t\t\t\t\t\tif (v.type === 'directory') {\n\t\t\t\t\t\t\t\treturn this.getData(await this.client.getDirectoryContents(v.filename, { signal }));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn [];\n\t\t\t\t\t\t}),\n\t\t\t\t\t)\n\t\t\t\t).flat();\n\t\t\t\tout = out.concat(...sub);\n\t\t\t\tcur = sub;\n\t\t\t}\n\t\t}\n\n\t\tif (glob) {\n\t\t\tconst { default: def, matcher = def.matcher } = await import('micromatch');\n\t\t\tconst match = matcher(glob);\n\t\t\tout = out.filter((v) => match(v.filename));\n\t\t}\n\t\tif (kind) {\n\t\t\tout = out.filter((v) => v.type === kind);\n\t\t}\n\t\tif (!hidden) {\n\t\t\tout = out.filter((v) => !v.basename.startsWith('.'));\n\t\t}\n\t\treturn out.map((stat) => this.toEntry(stat));\n\t}\n\n\tasync stat(path: string, { signal }: StatOptions = {}): Promise<IFileStat> {\n\t\tconst res = await this.client.stat(path, { details: true, signal });\n\t\treturn this.toEntry(this.getData(res));\n\t}\n\n\tasync mkdir(path: string, { recursive, signal }: MkdirOptions = {}): Promise<void> {\n\t\tawait this.client.createDirectory(path, { recursive, signal });\n\t}\n\n\tasync readFile(path: string, options: ReadFileOptions = {}): Promise<any> {\n\t\tconst format = options.encoding === 'text' ? 'text' : 'binary';\n\t\tconst res = await this.client.getFileContents(path, { format, ...options });\n\t\treturn this.getData(res);\n\t}\n\n\tasync writeFile(path: string, data: string | Buffer | ArrayBuffer | Readable, options = {}): Promise<void> {\n\t\tawait this.client.putFileContents(path, data, options);\n\t}\n\n\tasync rm(path: string, { signal, force, recursive }: RmOptions = {}): Promise<void> {\n\t\ttry {\n\t\t\tawait this.client.deleteFile(path);\n\t\t} catch (e: any) {\n\t\t\tif (force && e.status === 404) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tasync rename(oldPath: string, newPath: string, options = {}): Promise<void> {\n\t\tawait this.client.moveFile(oldPath, newPath, options);\n\t}\n\n\tasync exists(path: string): Promise<boolean> {\n\t\treturn await this.client.exists(path);\n\t}\n\n\tasync copy(src: string, dest: string, options = {}): Promise<void> {\n\t\tawait this.client.copyFile(src, dest, options);\n\t}\n\n\tcreateReadStream(path: string, options = {}): Readable {\n\t\treturn this.client.createReadStream(path, options);\n\t}\n\n\tcreateWriteStream(path: string, options = {}): Writable {\n\t\treturn this.client.createWriteStream(path, options);\n\t}\n}\n"],"names":["maybeFunction","createWebDavFileSystem","client","fs","WebdavFS","_client","Error","toEntry","input","filename","path","basename","lastmod","type","kind","etag","size","mime","meta","directory","substring","lastIndexOf","name","mtime","Date","getData","status","data","readdir","glob","recursive","depth","hidden","signal","o","deep","res","getDirectoryContents","out","l","cur","sub","Promise","all","map","v","flat","concat","default","def","matcher","match","filter","startsWith","stat","details","mkdir","createDirectory","readFile","options","format","encoding","getFileContents","writeFile","putFileContents","rm","force","deleteFile","e","rename","oldPath","newPath","moveFile","exists","copy","src","dest","copyFile","createReadStream","createWriteStream"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/fs/createWebDavFileSystem.ts"],"sourcesContent":["import type { Readable, Writable } from 'node:stream';\nimport { maybeFunction, type MaybeFunction } from '@wener/utils';\nimport type { FileStat, GetDirectoryContentsOptions, ResponseDataDetailed, WebDAVClient } from 'webdav';\nimport type {\n\tIFileStat,\n\tIFileSystem,\n\tMkdirOptions,\n\tReaddirOptions,\n\tReadFileOptions,\n\tRmOptions,\n\tStatOptions,\n\tWritableData,\n\tWriteFileOptions,\n} from './IFileSystem';\n\nexport function createWebDavFileSystem({ client }: { client: MaybeFunction<WebDAVClient> }): IFileSystem {\n\tlet fs = new WebdavFS({ client });\n\treturn fs;\n}\n\nclass WebdavFS implements IFileSystem {\n\t_client: MaybeFunction<WebDAVClient>;\n\n\tconstructor({\n\t\tclient = () => {\n\t\t\tthrow new Error('WebdavFS client not initialized');\n\t\t},\n\t}: {\n\t\tclient?: MaybeFunction<WebDAVClient>;\n\t}) {\n\t\tthis._client = client;\n\t}\n\n\tset client(client: MaybeFunction<WebDAVClient>) {\n\t\tthis._client = client;\n\t}\n\n\tget client(): WebDAVClient {\n\t\treturn maybeFunction(this._client);\n\t}\n\n\tprivate toEntry(input: FileStat): IFileStat {\n\t\tconst { filename: path, basename, lastmod, type: kind, etag, size, mime } = input;\n\t\tlet meta: Record<string, any> = {};\n\t\tif (etag) {\n\t\t\tmeta.etag = etag;\n\t\t}\n\t\tif (mime) {\n\t\t\tmeta.mime = mime;\n\t\t}\n\t\treturn {\n\t\t\tdirectory: path.substring(0, path.lastIndexOf('/')) || '/',\n\t\t\tpath,\n\t\t\tname: basename,\n\t\t\tmtime: +new Date(lastmod),\n\t\t\tkind,\n\t\t\tmeta,\n\t\t\tsize,\n\t\t};\n\t}\n\n\tprivate getData<T>(input: ResponseDataDetailed<T> | T): T {\n\t\tif (\n\t\t\tinput &&\n\t\t\ttypeof input === 'object' &&\n\t\t\t'data' in input &&\n\t\t\t// 'headers' in input &&\n\t\t\t'status' in input &&\n\t\t\ttypeof input.status === 'number'\n\t\t) {\n\t\t\treturn input.data;\n\t\t}\n\t\treturn input as T;\n\t}\n\n\tasync readdir(\n\t\tpath: string,\n\t\t{ glob, recursive, depth, kind, hidden, signal }: ReaddirOptions = {},\n\t): Promise<IFileStat[]> {\n\t\t// webdav depth 只支持 0,1\n\t\tlet o: GetDirectoryContentsOptions = {};\n\t\tif (recursive) {\n\t\t\to.deep = true;\n\t\t}\n\t\tlet res = await this.client.getDirectoryContents(path, {\n\t\t\tdeep: recursive,\n\t\t\tsignal,\n\t\t});\n\n\t\tlet out: FileStat[] = this.getData(res);\n\n\t\tif (!recursive && typeof depth === 'number' && depth >= 2) {\n\t\t\tlet l = depth;\n\t\t\tlet cur = out;\n\t\t\twhile (l-- > 1) {\n\t\t\t\tlet sub = (\n\t\t\t\t\tawait Promise.all(\n\t\t\t\t\t\tcur.map(async (v) => {\n\t\t\t\t\t\t\tif (v.type === 'directory') {\n\t\t\t\t\t\t\t\treturn this.getData(await this.client.getDirectoryContents(v.filename, { signal }));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn [];\n\t\t\t\t\t\t}),\n\t\t\t\t\t)\n\t\t\t\t).flat();\n\t\t\t\tout = out.concat(...sub);\n\t\t\t\tcur = sub;\n\t\t\t}\n\t\t}\n\n\t\tif (glob) {\n\t\t\tconst { default: def, matcher = def.matcher } = await import('micromatch');\n\t\t\tconst match = matcher(glob);\n\t\t\tout = out.filter((v) => match(v.filename));\n\t\t}\n\t\tif (kind) {\n\t\t\tout = out.filter((v) => v.type === kind);\n\t\t}\n\t\tif (!hidden) {\n\t\t\tout = out.filter((v) => !v.basename.startsWith('.'));\n\t\t}\n\t\treturn out.map((stat) => this.toEntry(stat));\n\t}\n\n\tasync stat(path: string, { signal }: StatOptions = {}): Promise<IFileStat> {\n\t\tconst res = await this.client.stat(path, { details: true, signal });\n\t\treturn this.toEntry(this.getData(res));\n\t}\n\n\tasync mkdir(path: string, { recursive, signal }: MkdirOptions = {}): Promise<void> {\n\t\tawait this.client.createDirectory(path, { recursive, signal });\n\t}\n\n\tasync readFile(path: string, options: ReadFileOptions = {}): Promise<any> {\n\t\tconst format = options.encoding === 'text' ? 'text' : 'binary';\n\t\tconst res = await this.client.getFileContents(path, { format, ...options });\n\t\treturn this.getData(res);\n\t}\n\n\tasync writeFile(path: string, data: WritableData, options: WriteFileOptions = {}): Promise<void> {\n\t\t// Convert web ReadableStream to something WebDAV client can handle\n\t\tlet webdavData: string | Buffer | ArrayBuffer | Readable = data as string | Buffer | ArrayBuffer | Readable;\n\t\tif (data instanceof ReadableStream) {\n\t\t\t// Convert web ReadableStream to Buffer\n\t\t\tconst reader = data.getReader();\n\t\t\tconst chunks: Uint8Array[] = [];\n\t\t\twhile (true) {\n\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\tif (done) break;\n\t\t\t\tif (value) chunks.push(value);\n\t\t\t}\n\t\t\twebdavData = Buffer.concat(chunks);\n\t\t} else if (ArrayBuffer.isView(data) && !(data instanceof Buffer)) {\n\t\t\t// Convert ArrayBufferView to Buffer\n\t\t\twebdavData = Buffer.from(data.buffer, data.byteOffset, data.byteLength);\n\t\t}\n\t\tawait this.client.putFileContents(path, webdavData, options);\n\t}\n\n\tasync rm(path: string, { signal: _signal, force, recursive: _recursive }: RmOptions = {}): Promise<void> {\n\t\ttry {\n\t\t\tawait this.client.deleteFile(path);\n\t\t} catch (e: any) {\n\t\t\tif (force && e.status === 404) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tasync rename(oldPath: string, newPath: string, options = {}): Promise<void> {\n\t\tawait this.client.moveFile(oldPath, newPath, options);\n\t}\n\n\tasync exists(path: string): Promise<boolean> {\n\t\treturn await this.client.exists(path);\n\t}\n\n\tasync copy(src: string, dest: string, options = {}): Promise<void> {\n\t\tawait this.client.copyFile(src, dest, options);\n\t}\n\n\tcreateReadStream(path: string, options = {}): Readable {\n\t\treturn this.client.createReadStream(path, options);\n\t}\n\n\tcreateWriteStream(path: string, options = {}): Writable {\n\t\treturn this.client.createWriteStream(path, options);\n\t}\n}\n"],"names":["maybeFunction","createWebDavFileSystem","client","fs","WebdavFS","_client","Error","toEntry","input","filename","path","basename","lastmod","type","kind","etag","size","mime","meta","directory","substring","lastIndexOf","name","mtime","Date","getData","status","data","readdir","glob","recursive","depth","hidden","signal","o","deep","res","getDirectoryContents","out","l","cur","sub","Promise","all","map","v","flat","concat","default","def","matcher","match","filter","startsWith","stat","details","mkdir","createDirectory","readFile","options","format","encoding","getFileContents","writeFile","webdavData","ReadableStream","reader","getReader","chunks","done","value","read","push","Buffer","ArrayBuffer","isView","from","buffer","byteOffset","byteLength","putFileContents","rm","_signal","force","_recursive","deleteFile","e","rename","oldPath","newPath","moveFile","exists","copy","src","dest","copyFile","createReadStream","createWriteStream"],"mappings":"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"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { basename, dirname, join, normalize } from "pathe";
|
|
2
|
+
import { FileSystemError } from "./FileSystemError.js";
|
|
3
|
+
export function createWebFileSystem(options) {
|
|
4
|
+
return new WebFileSystem(options);
|
|
5
|
+
}
|
|
6
|
+
let WebFileSystem = class WebFileSystem {
|
|
7
|
+
root;
|
|
8
|
+
constructor({ root }) {
|
|
9
|
+
this.root = root;
|
|
10
|
+
}
|
|
11
|
+
async _getHandle(path) {
|
|
12
|
+
const parts = normalize(path).split("/").filter(Boolean);
|
|
13
|
+
if (parts.length === 0)
|
|
14
|
+
return this.root;
|
|
15
|
+
let current = this.root;
|
|
16
|
+
for (let i = 0; i < parts.length; i++) {
|
|
17
|
+
const part = parts[i];
|
|
18
|
+
const isLast = i === parts.length - 1;
|
|
19
|
+
try {
|
|
20
|
+
// Try to get as directory first
|
|
21
|
+
current = await current.getDirectoryHandle(part);
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
if (e.name === "TypeMismatchError" || e.name === "NotFoundError") {
|
|
25
|
+
if (isLast) {
|
|
26
|
+
// Might be a file
|
|
27
|
+
try {
|
|
28
|
+
return await current.getFileHandle(part);
|
|
29
|
+
}
|
|
30
|
+
catch (_e2) {
|
|
31
|
+
throw new FileSystemError(`File not found: ${path}`, "ENOENT");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (e.name === "NotFoundError") {
|
|
36
|
+
throw new FileSystemError(`Path not found: ${path}`, "ENOENT");
|
|
37
|
+
}
|
|
38
|
+
throw e;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return current;
|
|
42
|
+
}
|
|
43
|
+
async _getParent(path) {
|
|
44
|
+
const normalized = normalize(path);
|
|
45
|
+
const parentPath = dirname(normalized);
|
|
46
|
+
const name = basename(normalized);
|
|
47
|
+
if (!name)
|
|
48
|
+
throw new FileSystemError("Invalid path", "EINVAL");
|
|
49
|
+
const parentHandle = await this._getHandle(parentPath);
|
|
50
|
+
if (parentHandle.kind !== "directory") {
|
|
51
|
+
throw new FileSystemError(`Parent is not a directory: ${parentPath}`, "ENOTDIR");
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
parent: parentHandle,
|
|
55
|
+
name
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
async stat(path, options) {
|
|
59
|
+
if (options?.signal?.aborted)
|
|
60
|
+
throw new FileSystemError("Operation aborted", "ABORT_ERR");
|
|
61
|
+
const handle = await this._getHandle(path);
|
|
62
|
+
return this._handleToStat(handle, path);
|
|
63
|
+
}
|
|
64
|
+
async _handleToStat(handle, path) {
|
|
65
|
+
let size = 0;
|
|
66
|
+
let mtime = 0;
|
|
67
|
+
if (handle.kind === "file") {
|
|
68
|
+
const file = await handle.getFile();
|
|
69
|
+
size = file.size;
|
|
70
|
+
mtime = file.lastModified;
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
path,
|
|
74
|
+
directory: dirname(path),
|
|
75
|
+
name: handle.name,
|
|
76
|
+
kind: handle.kind,
|
|
77
|
+
size,
|
|
78
|
+
mtime,
|
|
79
|
+
meta: {}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
async exists(path) {
|
|
83
|
+
try {
|
|
84
|
+
await this._getHandle(path);
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async readdir(path, options) {
|
|
92
|
+
if (options?.signal?.aborted)
|
|
93
|
+
throw new FileSystemError("Operation aborted", "ABORT_ERR");
|
|
94
|
+
const handle = await this._getHandle(path);
|
|
95
|
+
if (handle.kind !== "directory") {
|
|
96
|
+
throw new FileSystemError(`Not a directory: ${path}`, "ENOTDIR");
|
|
97
|
+
}
|
|
98
|
+
const entries = [];
|
|
99
|
+
// @ts-expect-error - FileSystemDirectoryHandle is async iterable in modern browsers
|
|
100
|
+
for await (const entry of handle.values()) {
|
|
101
|
+
entries.push(await this._handleToStat(entry, join(path, entry.name)));
|
|
102
|
+
}
|
|
103
|
+
return entries;
|
|
104
|
+
}
|
|
105
|
+
async mkdir(path, options) {
|
|
106
|
+
if (options?.signal?.aborted)
|
|
107
|
+
throw new FileSystemError("Operation aborted", "ABORT_ERR");
|
|
108
|
+
const normalized = normalize(path);
|
|
109
|
+
const parts = normalized.split("/").filter(Boolean);
|
|
110
|
+
let current = this.root;
|
|
111
|
+
if (options?.recursive) {
|
|
112
|
+
for (const part of parts) {
|
|
113
|
+
current = await current.getDirectoryHandle(part, {
|
|
114
|
+
create: true
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
const parentPath = dirname(normalized);
|
|
120
|
+
const name = basename(normalized);
|
|
121
|
+
try {
|
|
122
|
+
const parent = await this._getHandle(parentPath);
|
|
123
|
+
if (parent.kind !== "directory")
|
|
124
|
+
throw new FileSystemError(`Parent not a directory: ${parentPath}`, "ENOTDIR");
|
|
125
|
+
await parent.getDirectoryHandle(name, {
|
|
126
|
+
create: true
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
catch (e) {
|
|
130
|
+
if (e.code === "ENOENT" || e.name === "NotFoundError") {
|
|
131
|
+
throw new FileSystemError(`Parent does not exist: ${parentPath}`, "ENOENT");
|
|
132
|
+
}
|
|
133
|
+
throw e;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
async readFile(path, options) {
|
|
138
|
+
if (options?.signal?.aborted)
|
|
139
|
+
throw new FileSystemError("Operation aborted", "ABORT_ERR");
|
|
140
|
+
const handle = await this._getHandle(path);
|
|
141
|
+
if (handle.kind !== "file")
|
|
142
|
+
throw new FileSystemError(`Is a directory: ${path}`, "EISDIR");
|
|
143
|
+
const file = await handle.getFile();
|
|
144
|
+
if (options?.encoding === "text") {
|
|
145
|
+
return await file.text();
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
const buffer = await file.arrayBuffer();
|
|
149
|
+
return new Uint8Array(buffer);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async writeFile(path, data, options) {
|
|
153
|
+
if (options?.signal?.aborted)
|
|
154
|
+
throw new FileSystemError("Operation aborted", "ABORT_ERR");
|
|
155
|
+
if (options?.overwrite === false) {
|
|
156
|
+
if (await this.exists(path)) {
|
|
157
|
+
throw new FileSystemError(`File already exists: ${path}`, "EEXIST");
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
const { parent, name } = await this._getParent(path);
|
|
161
|
+
const handle = await parent.getFileHandle(name, {
|
|
162
|
+
create: true
|
|
163
|
+
});
|
|
164
|
+
const writable = await handle.createWritable();
|
|
165
|
+
await writable.write(data);
|
|
166
|
+
await writable.close();
|
|
167
|
+
}
|
|
168
|
+
async rm(path, options) {
|
|
169
|
+
if (options?.signal?.aborted)
|
|
170
|
+
throw new FileSystemError("Operation aborted", "ABORT_ERR");
|
|
171
|
+
const { parent, name } = await this._getParent(path);
|
|
172
|
+
try {
|
|
173
|
+
await parent.removeEntry(name, {
|
|
174
|
+
recursive: options?.recursive
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
catch (e) {
|
|
178
|
+
if (e.name === "NotFoundError") {
|
|
179
|
+
if (!options?.force)
|
|
180
|
+
throw new FileSystemError(`File not found: ${path}`, "ENOENT");
|
|
181
|
+
}
|
|
182
|
+
else if (e.name === "InvalidModificationError") {
|
|
183
|
+
throw new FileSystemError(`Directory not empty: ${path}`, "ENOTEMPTY");
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
throw e;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
async rename(oldPath, newPath, options) {
|
|
191
|
+
if (options?.signal?.aborted)
|
|
192
|
+
throw new FileSystemError("Operation aborted", "ABORT_ERR");
|
|
193
|
+
// File System Access API doesn't support move/rename directly
|
|
194
|
+
// Fallback to copy + delete
|
|
195
|
+
await this.copy(oldPath, newPath, {
|
|
196
|
+
overwrite: options?.overwrite
|
|
197
|
+
});
|
|
198
|
+
await this.rm(oldPath, {
|
|
199
|
+
recursive: true
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
async copy(src, dest, options) {
|
|
203
|
+
if (options?.signal?.aborted)
|
|
204
|
+
throw new FileSystemError("Operation aborted", "ABORT_ERR");
|
|
205
|
+
const srcHandle = await this._getHandle(src);
|
|
206
|
+
if (srcHandle.kind === "file") {
|
|
207
|
+
const file = await srcHandle.getFile();
|
|
208
|
+
await this.writeFile(dest, await file.arrayBuffer(), {
|
|
209
|
+
overwrite: options?.overwrite
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
// Directory copy
|
|
214
|
+
await this.mkdir(dest);
|
|
215
|
+
const entries = await this.readdir(src);
|
|
216
|
+
for (const entry of entries) {
|
|
217
|
+
await this.copy(entry.path, join(dest, entry.name), options);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
getUrl(_file) {
|
|
222
|
+
return undefined;
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
//# sourceMappingURL=createWebFileSystem.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/fs/createWebFileSystem.ts"],"sourcesContent":["import { basename, dirname, join, normalize } from 'pathe';\nimport { FileSystemError } from './FileSystemError';\nimport type {\n\tCopyOptions,\n\tIFileStat,\n\tIFileSystem,\n\tMkdirOptions,\n\tReadFileOptions,\n\tReaddirOptions,\n\tRenameOptions,\n\tRmOptions,\n\tStatOptions,\n\tWriteFileOptions,\n} from './IFileSystem';\n\nexport function createWebFileSystem(options: { root: FileSystemDirectoryHandle }): IFileSystem {\n\treturn new WebFileSystem(options);\n}\n\nclass WebFileSystem implements IFileSystem {\n\tprivate readonly root: FileSystemDirectoryHandle;\n\n\tconstructor({ root }: { root: FileSystemDirectoryHandle }) {\n\t\tthis.root = root;\n\t}\n\n\tprivate async _getHandle(path: string): Promise<FileSystemHandle> {\n\t\tconst parts = normalize(path).split('/').filter(Boolean);\n\t\tif (parts.length === 0) return this.root;\n\n\t\tlet current: FileSystemDirectoryHandle = this.root;\n\n\t\tfor (let i = 0; i < parts.length; i++) {\n\t\t\tconst part = parts[i];\n\t\t\tconst isLast = i === parts.length - 1;\n\n\t\t\ttry {\n\t\t\t\t// Try to get as directory first\n\t\t\t\tcurrent = await current.getDirectoryHandle(part);\n\t\t\t} catch (e: any) {\n\t\t\t\tif (e.name === 'TypeMismatchError' || e.name === 'NotFoundError') {\n\t\t\t\t\tif (isLast) {\n\t\t\t\t\t\t// Might be a file\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\treturn await current.getFileHandle(part);\n\t\t\t\t\t\t} catch (_e2) {\n\t\t\t\t\t\t\tthrow new FileSystemError(`File not found: ${path}`, 'ENOENT');\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (e.name === 'NotFoundError') {\n\t\t\t\t\tthrow new FileSystemError(`Path not found: ${path}`, 'ENOENT');\n\t\t\t\t}\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t}\n\n\tprivate async _getParent(path: string): Promise<{ parent: FileSystemDirectoryHandle; name: string }> {\n\t\tconst normalized = normalize(path);\n\t\tconst parentPath = dirname(normalized);\n\t\tconst name = basename(normalized);\n\n\t\tif (!name) throw new FileSystemError('Invalid path', 'EINVAL');\n\n\t\tconst parentHandle = await this._getHandle(parentPath);\n\t\tif (parentHandle.kind !== 'directory') {\n\t\t\tthrow new FileSystemError(`Parent is not a directory: ${parentPath}`, 'ENOTDIR');\n\t\t}\n\n\t\treturn { parent: parentHandle as FileSystemDirectoryHandle, name };\n\t}\n\n\tasync stat(path: string, options?: StatOptions): Promise<IFileStat> {\n\t\tif (options?.signal?.aborted) throw new FileSystemError('Operation aborted', 'ABORT_ERR');\n\n\t\tconst handle = await this._getHandle(path);\n\t\treturn this._handleToStat(handle, path);\n\t}\n\n\tprivate async _handleToStat(handle: FileSystemHandle, path: string): Promise<IFileStat> {\n\t\tlet size = 0;\n\t\tlet mtime = 0;\n\n\t\tif (handle.kind === 'file') {\n\t\t\tconst file = await (handle as FileSystemFileHandle).getFile();\n\t\t\tsize = file.size;\n\t\t\tmtime = file.lastModified;\n\t\t}\n\n\t\treturn {\n\t\t\tpath,\n\t\t\tdirectory: dirname(path),\n\t\t\tname: handle.name,\n\t\t\tkind: handle.kind,\n\t\t\tsize,\n\t\t\tmtime,\n\t\t\tmeta: {},\n\t\t};\n\t}\n\n\tasync exists(path: string): Promise<boolean> {\n\t\ttry {\n\t\t\tawait this._getHandle(path);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tasync readdir(path: string, options?: ReaddirOptions): Promise<IFileStat[]> {\n\t\tif (options?.signal?.aborted) throw new FileSystemError('Operation aborted', 'ABORT_ERR');\n\n\t\tconst handle = await this._getHandle(path);\n\t\tif (handle.kind !== 'directory') {\n\t\t\tthrow new FileSystemError(`Not a directory: ${path}`, 'ENOTDIR');\n\t\t}\n\n\t\tconst entries: IFileStat[] = [];\n\t\t// @ts-expect-error - FileSystemDirectoryHandle is async iterable in modern browsers\n\t\tfor await (const entry of (handle as FileSystemDirectoryHandle).values()) {\n\t\t\tentries.push(await this._handleToStat(entry, join(path, entry.name)));\n\t\t}\n\t\treturn entries;\n\t}\n\n\tasync mkdir(path: string, options?: MkdirOptions): Promise<void> {\n\t\tif (options?.signal?.aborted) throw new FileSystemError('Operation aborted', 'ABORT_ERR');\n\n\t\tconst normalized = normalize(path);\n\t\tconst parts = normalized.split('/').filter(Boolean);\n\t\tlet current = this.root;\n\n\t\tif (options?.recursive) {\n\t\t\tfor (const part of parts) {\n\t\t\t\tcurrent = await current.getDirectoryHandle(part, { create: true });\n\t\t\t}\n\t\t} else {\n\t\t\tconst parentPath = dirname(normalized);\n\t\t\tconst name = basename(normalized);\n\t\t\ttry {\n\t\t\t\tconst parent = await this._getHandle(parentPath);\n\t\t\t\tif (parent.kind !== 'directory') throw new FileSystemError(`Parent not a directory: ${parentPath}`, 'ENOTDIR');\n\t\t\t\tawait (parent as FileSystemDirectoryHandle).getDirectoryHandle(name, { create: true });\n\t\t\t} catch (e: any) {\n\t\t\t\tif (e.code === 'ENOENT' || e.name === 'NotFoundError') {\n\t\t\t\t\tthrow new FileSystemError(`Parent does not exist: ${parentPath}`, 'ENOENT');\n\t\t\t\t}\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t}\n\t}\n\n\treadFile(path: string, options?: ReadFileOptions & { encoding: 'text' }): Promise<string>;\n\treadFile(path: string, options?: ReadFileOptions): Promise<Uint8Array>;\n\tasync readFile(path: string, options?: ReadFileOptions): Promise<string | Uint8Array> {\n\t\tif (options?.signal?.aborted) throw new FileSystemError('Operation aborted', 'ABORT_ERR');\n\n\t\tconst handle = await this._getHandle(path);\n\t\tif (handle.kind !== 'file') throw new FileSystemError(`Is a directory: ${path}`, 'EISDIR');\n\n\t\tconst file = await (handle as FileSystemFileHandle).getFile();\n\n\t\tif (options?.encoding === 'text') {\n\t\t\treturn await file.text();\n\t\t} else {\n\t\t\tconst buffer = await file.arrayBuffer();\n\t\t\treturn new Uint8Array(buffer);\n\t\t}\n\t}\n\n\tasync writeFile(\n\t\tpath: string,\n\t\tdata: string | ArrayBuffer | ArrayBufferView<ArrayBufferLike> | ReadableStream,\n\t\toptions?: WriteFileOptions,\n\t): Promise<void> {\n\t\tif (options?.signal?.aborted) throw new FileSystemError('Operation aborted', 'ABORT_ERR');\n\n\t\tif (options?.overwrite === false) {\n\t\t\tif (await this.exists(path)) {\n\t\t\t\tthrow new FileSystemError(`File already exists: ${path}`, 'EEXIST');\n\t\t\t}\n\t\t}\n\n\t\tconst { parent, name } = await this._getParent(path);\n\t\tconst handle = await parent.getFileHandle(name, { create: true });\n\n\t\tconst writable = await (handle as any).createWritable();\n\t\tawait writable.write(data);\n\t\tawait writable.close();\n\t}\n\n\tasync rm(path: string, options?: RmOptions): Promise<void> {\n\t\tif (options?.signal?.aborted) throw new FileSystemError('Operation aborted', 'ABORT_ERR');\n\n\t\tconst { parent, name } = await this._getParent(path);\n\n\t\ttry {\n\t\t\tawait (parent as any).removeEntry(name, { recursive: options?.recursive });\n\t\t} catch (e: any) {\n\t\t\tif (e.name === 'NotFoundError') {\n\t\t\t\tif (!options?.force) throw new FileSystemError(`File not found: ${path}`, 'ENOENT');\n\t\t\t} else if (e.name === 'InvalidModificationError') {\n\t\t\t\tthrow new FileSystemError(`Directory not empty: ${path}`, 'ENOTEMPTY');\n\t\t\t} else {\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t}\n\t}\n\n\tasync rename(oldPath: string, newPath: string, options?: RenameOptions): Promise<void> {\n\t\tif (options?.signal?.aborted) throw new FileSystemError('Operation aborted', 'ABORT_ERR');\n\n\t\t// File System Access API doesn't support move/rename directly\n\t\t// Fallback to copy + delete\n\t\tawait this.copy(oldPath, newPath, { overwrite: options?.overwrite });\n\t\tawait this.rm(oldPath, { recursive: true });\n\t}\n\n\tasync copy(src: string, dest: string, options?: CopyOptions): Promise<void> {\n\t\tif (options?.signal?.aborted) throw new FileSystemError('Operation aborted', 'ABORT_ERR');\n\n\t\tconst srcHandle = await this._getHandle(src);\n\n\t\tif (srcHandle.kind === 'file') {\n\t\t\tconst file = await (srcHandle as FileSystemFileHandle).getFile();\n\t\t\tawait this.writeFile(dest, await file.arrayBuffer(), { overwrite: options?.overwrite });\n\t\t} else {\n\t\t\t// Directory copy\n\t\t\tawait this.mkdir(dest);\n\t\t\tconst entries = await this.readdir(src);\n\t\t\tfor (const entry of entries) {\n\t\t\t\tawait this.copy(entry.path, join(dest, entry.name), options);\n\t\t\t}\n\t\t}\n\t}\n\n\tgetUrl(_file: IFileStat | string): string | undefined {\n\t\treturn undefined;\n\t}\n}\n"],"names":["basename","dirname","join","normalize","FileSystemError","createWebFileSystem","options","WebFileSystem","root","_getHandle","path","parts","split","filter","Boolean","length","current","i","part","isLast","getDirectoryHandle","e","name","getFileHandle","_e2","_getParent","normalized","parentPath","parentHandle","kind","parent","stat","signal","aborted","handle","_handleToStat","size","mtime","file","getFile","lastModified","directory","meta","exists","readdir","entries","entry","values","push","mkdir","recursive","create","code","readFile","encoding","text","buffer","arrayBuffer","Uint8Array","writeFile","data","overwrite","writable","createWritable","write","close","rm","removeEntry","force","rename","oldPath","newPath","copy","src","dest","srcHandle","getUrl","_file","undefined"],"mappings":"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"}
|
package/lib/fs/findMimeType.js
CHANGED
|
@@ -7,7 +7,7 @@ export function findMimeType(path) {
|
|
|
7
7
|
return false;
|
|
8
8
|
}
|
|
9
9
|
// get the extension ("ext" or ".ext" or full path)
|
|
10
|
-
const extension = pathe.extname(
|
|
10
|
+
const extension = pathe.extname(`x.${path}`).toLowerCase().slice(1);
|
|
11
11
|
if (!extension) {
|
|
12
12
|
return false;
|
|
13
13
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/fs/findMimeType.ts"],"sourcesContent":["import { types } from 'mime-types';\nimport pathe from 'pathe';\n\nexport function findMimeType(path: string | undefined | null) {\n\t// fix extname error\n\t// https://github.com/jshttp/mime-types/issues/111\n\n\tif (!path || typeof path !== 'string') {\n\t\treturn false;\n\t}\n\n\t// get the extension (\"ext\" or \".ext\" or full path)\n\tconst extension = pathe
|
|
1
|
+
{"version":3,"sources":["../../src/fs/findMimeType.ts"],"sourcesContent":["import { types } from 'mime-types';\nimport pathe from 'pathe';\n\nexport function findMimeType(path: string | undefined | null) {\n\t// fix extname error\n\t// https://github.com/jshttp/mime-types/issues/111\n\n\tif (!path || typeof path !== 'string') {\n\t\treturn false;\n\t}\n\n\t// get the extension (\"ext\" or \".ext\" or full path)\n\tconst extension = pathe.extname(`x.${path}`).toLowerCase().slice(1);\n\n\tif (!extension) {\n\t\treturn false;\n\t}\n\n\treturn types[extension] || false;\n}\n"],"names":["types","pathe","findMimeType","path","extension","extname","toLowerCase","slice"],"mappings":"AAAA,SAASA,KAAK,QAAQ,aAAa;AACnC,OAAOC,WAAW,QAAQ;AAE1B,OAAO,SAASC,aAAaC,IAA+B;IAC3D,oBAAoB;IACpB,kDAAkD;IAElD,IAAI,CAACA,QAAQ,OAAOA,SAAS,UAAU;QACtC,OAAO;IACR;IAEA,mDAAmD;IACnD,MAAMC,YAAYH,MAAMI,OAAO,CAAC,CAAC,EAAE,EAAEF,MAAM,EAAEG,WAAW,GAAGC,KAAK,CAAC;IAEjE,IAAI,CAACH,WAAW;QACf,OAAO;IACR;IAEA,OAAOJ,KAAK,CAACI,UAAU,IAAI;AAC5B"}
|
package/lib/fs/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { createSandboxFileSystem } from "./createSandboxFileSystem.js";
|
|
2
2
|
export { createMemoryFileSystem } from "./createMemoryFileSystem.js";
|
|
3
|
-
export { createWebDavFileSystem } from "./createWebDavFileSystem.js";
|
|
4
3
|
export { createBrowserFileSystem } from "./createBrowserFileSystem.js";
|
|
4
|
+
export { createWebFileSystem } from "./createWebFileSystem.js";
|
|
5
5
|
export { findMimeType } from "./findMimeType.js";
|
|
6
6
|
export { FileUrlOptionsSchema } from "./types.js";
|
|
7
7
|
export { FileSystemError, FileSystemErrorCode } from "./FileSystemError.js";
|
package/lib/fs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/fs/index.ts"],"sourcesContent":["export type * from './IFileSystem';\nexport { createSandboxFileSystem } from './createSandboxFileSystem';\nexport { createMemoryFileSystem } from './createMemoryFileSystem';\nexport {
|
|
1
|
+
{"version":3,"sources":["../../src/fs/index.ts"],"sourcesContent":["export type * from './IFileSystem';\nexport { createSandboxFileSystem } from './createSandboxFileSystem';\nexport { createMemoryFileSystem } from './createMemoryFileSystem';\nexport { createBrowserFileSystem } from './createBrowserFileSystem';\nexport { createWebFileSystem } from './createWebFileSystem';\nexport { findMimeType } from './findMimeType';\nexport { type FileUrlOptions, FileUrlOptionsSchema } from './types';\nexport { FileSystemError, FileSystemErrorCode } from './FileSystemError';\n"],"names":["createSandboxFileSystem","createMemoryFileSystem","createBrowserFileSystem","createWebFileSystem","findMimeType","FileUrlOptionsSchema","FileSystemError","FileSystemErrorCode"],"mappings":"AACA,SAASA,uBAAuB,QAAQ,4BAA4B;AACpE,SAASC,sBAAsB,QAAQ,2BAA2B;AAClE,SAASC,uBAAuB,QAAQ,4BAA4B;AACpE,SAASC,mBAAmB,QAAQ,wBAAwB;AAC5D,SAASC,YAAY,QAAQ,iBAAiB;AAC9C,SAA8BC,oBAAoB,QAAQ,UAAU;AACpE,SAASC,eAAe,EAAEC,mBAAmB,QAAQ,oBAAoB"}
|