@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/fs/minio/createMinioFileSystem.ts"],"sourcesContent":["import { basename, dirname, normalize } from 'pathe';\nimport { PassThrough, Readable, type Writable } from 'node:stream';\nimport { parseS3Url, type ParseS3UrlOptions } from '@wener/common/s3';\nimport { Client } from 'minio';\nimport type {\n\tCopyOptions,\n\tCreateReadStreamOptions,\n\tCreateWriteStreamOptions,\n\tIFileStat,\n\tIFileSystem,\n\tMkdirOptions,\n\tReaddirOptions,\n\tReadFileOptions,\n\tRenameOptions,\n\tRmOptions,\n\tStatOptions,\n\tWriteFileOptions,\n} from '../IFileSystem';\n\nexport type CreateMinioFileSystemOptions = ParseS3UrlOptions & {\n\tclient?: Client;\n\t/**\n\t * Optional prefix to scope all operations within a specific folder in the bucket.\n\t * All file operations will be relative to this prefix.\n\t * Should not include leading or trailing slashes.\n\t * Example: 'data/uploads' or 'backups/2024'\n\t */\n\tprefix?: string;\n};\n\nexport function createMinioFileSystem(options: CreateMinioFileSystemOptions = {}): MinioFS {\n\tconst parsed = parseS3Url(options);\n\tif (!parsed) {\n\t\tthrow new Error('S3 URL or connection options are required');\n\t}\n\n\tconst { client, prefix } = options;\n\tif (!client && (!parsed.endpoint || !parsed.bucket)) {\n\t\tthrow new Error('S3 endpoint and bucket are required when client is not provided');\n\t}\n\n\tlet minioClient: Client;\n\tlet bucket: string;\n\n\tif (client) {\n\t\tminioClient = client;\n\t\tbucket = parsed.bucket || '';\n\t} else {\n\t\tbucket = parsed.bucket || '';\n\n\t\t// Import Minio dynamically to avoid requiring it as a dependency\n\t\tminioClient = new Client({\n\t\t\tendPoint: parsed.endpoint,\n\t\t\tport: parsed.port,\n\t\t\tuseSSL: parsed.useSsl ?? true,\n\t\t\taccessKey: parsed.accessKeyId || '',\n\t\t\tsecretKey: parsed.secretAccessKey || '',\n\t\t\tregion: parsed.region,\n\t\t\tpathStyle: parsed.pathStyle,\n\t\t});\n\t}\n\n\t// Normalize prefix: remove leading/trailing slashes\n\tconst normalizedPrefix = prefix ? prefix.replace(/^\\/+/, '').replace(/\\/+$/, '') : '';\n\n\treturn new MinioFS(minioClient, bucket, normalizedPrefix);\n}\n\nclass MinioFS implements IFileSystem {\n\tconstructor(\n\t\tprivate readonly client: Client,\n\t\tprivate readonly bucket: string,\n\t\tprivate readonly prefix: string = '',\n\t) {}\n\n\t/**\n\t * Normalize path to S3 key format (remove leading slash, handle relative paths)\n\t * and prepend the prefix if one is set\n\t */\n\tprivate normalizeKey(path: string): string {\n\t\tif (!path || path === '/') {\n\t\t\treturn this.prefix;\n\t\t}\n\t\tconst normalized = normalize(path).replace(/^\\/+/, '').replace(/\\\\/g, '/');\n\n\t\t// Prepend prefix if set\n\t\tif (this.prefix) {\n\t\t\treturn this.prefix + '/' + normalized;\n\t\t}\n\t\treturn normalized;\n\t}\n\n\t/**\n\t * Remove prefix from S3 key to get the file system path\n\t */\n\tprivate stripPrefix(key: string): string {\n\t\tif (!key) {\n\t\t\treturn '/';\n\t\t}\n\t\t// If key is just the prefix (or empty after stripping), return root\n\t\tif (this.prefix && key === this.prefix) {\n\t\t\treturn '/';\n\t\t}\n\t\tif (!this.prefix || !key.startsWith(this.prefix + '/')) {\n\t\t\treturn key.startsWith('/') ? key : '/' + key;\n\t\t}\n\t\tconst withoutPrefix = key.slice(this.prefix.length);\n\t\treturn withoutPrefix || '/';\n\t}\n\n\t/**\n\t * Convert S3 key back to file system path (strip prefix and add leading slash)\n\t */\n\tprivate keyToPath(key: string): string {\n\t\tif (!key) {\n\t\t\treturn '/';\n\t\t}\n\t\treturn this.stripPrefix(key);\n\t}\n\n\t/**\n\t * Get directory path from a key\n\t */\n\tprivate getDirectory(key: string): string {\n\t\tif (!key) {\n\t\t\treturn '/';\n\t\t}\n\t\tconst dir = dirname(key).replace(/\\\\/g, '/');\n\t\treturn dir === '.' ? '/' : '/' + dir;\n\t}\n\n\t/**\n\t * Check if a key represents a directory (ends with /)\n\t */\n\tprivate isDirectoryKey(key: string): boolean {\n\t\treturn key.endsWith('/');\n\t}\n\n\t/**\n\t * Convert MinIO object metadata to IFileStat\n\t */\n\tprivate toFileStat(key: string, obj: { name: string; size: number; lastModified: Date; etag?: string }): IFileStat {\n\t\tconst isDir = this.isDirectoryKey(key);\n\t\tconst path = this.keyToPath(key);\n\t\tconst directory = this.getDirectory(key);\n\n\t\treturn {\n\t\t\tdirectory,\n\t\t\tpath,\n\t\t\tname: isDir ? basename(key.slice(0, -1)) || basename(directory) || '/' : basename(key),\n\t\t\tkind: isDir ? 'directory' : 'file',\n\t\t\tmtime: obj.lastModified ? new Date(obj.lastModified).getTime() : Date.now(),\n\t\t\tsize: obj.size || 0,\n\t\t\tmeta: {\n\t\t\t\t...(obj.etag ? { etag: obj.etag.replace(/\"/g, '') } : {}),\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate checkAborted(signal?: AbortSignal): void {\n\t\tif (signal?.aborted) {\n\t\t\tthrow new Error('The operation was aborted');\n\t\t}\n\t}\n\n\tasync readdir(dir: string, options: ReaddirOptions = {}): Promise<IFileStat[]> {\n\t\tconst { glob, recursive, depth = 1, kind, hidden = true, signal } = options;\n\t\tthis.checkAborted(signal);\n\n\t\tconst dirPrefix = this.normalizeKey(dir);\n\t\tconst prefixWithSlash = dirPrefix ? (dirPrefix.endsWith('/') ? dirPrefix : dirPrefix + '/') : '';\n\n\t\ttry {\n\t\t\t// MinIO listObjects supports recursive option\n\t\t\t// When recursive=false, MinIO uses delimiter='/' internally to return CommonPrefixes\n\t\t\tconst objects: Array<{ name: string; prefix?: string; size: number; lastModified: Date; etag: string }> = [];\n\t\t\tconst commonPrefixes: string[] = [];\n\n\t\t\t// MinIO listObjects returns a stream\n\t\t\t// When recursive=false, it returns both objects and prefixes (CommonPrefixes)\n\t\t\tconst objectStream = this.client.listObjects(this.bucket, prefixWithSlash, recursive);\n\n\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\tobjectStream.on('data', (obj: any) => {\n\t\t\t\t\tif (obj.name) {\n\t\t\t\t\t\tobjects.push({\n\t\t\t\t\t\t\tname: obj.name,\n\t\t\t\t\t\t\tsize: obj.size || 0,\n\t\t\t\t\t\t\tlastModified: obj.lastModified || new Date(),\n\t\t\t\t\t\t\tetag: obj.etag || '',\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (obj.prefix) {\n\t\t\t\t\t\t// CommonPrefixes from MinIO\n\t\t\t\t\t\tcommonPrefixes.push(obj.prefix);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tobjectStream.on('end', () => {\n\t\t\t\t\tresolve();\n\t\t\t\t});\n\n\t\t\t\tobjectStream.on('error', (err: any) => {\n\t\t\t\t\treject(err);\n\t\t\t\t});\n\n\t\t\t\tif (signal) {\n\t\t\t\t\tsignal.addEventListener('abort', () => {\n\t\t\t\t\t\tobjectStream.destroy();\n\t\t\t\t\t\treject(new Error('The operation was aborted'));\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tlet results: IFileStat[] = [];\n\n\t\t\t// Process CommonPrefixes (directories) first\n\t\t\tfor (const prefix of commonPrefixes) {\n\t\t\t\tthis.checkAborted(signal);\n\n\t\t\t\t// Skip if not under our prefix\n\t\t\t\tif (prefixWithSlash && !prefix.startsWith(prefixWithSlash)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Get relative path\n\t\t\t\tconst relativePrefix = prefixWithSlash ? prefix.slice(prefixWithSlash.length) : prefix;\n\t\t\t\tconst dirName = relativePrefix.replace(/\\/$/, ''); // Remove trailing slash\n\n\t\t\t\tif (!dirName) continue;\n\n\t\t\t\t// For non-recursive, only show immediate children\n\t\t\t\tif (!recursive && depth === 1) {\n\t\t\t\t\tconst firstSlash = dirName.indexOf('/');\n\t\t\t\t\tif (firstSlash >= 0) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst dirKey = prefix.endsWith('/') ? prefix : prefix + '/';\n\t\t\t\tconst stat = this.toFileStat(dirKey, {\n\t\t\t\t\tname: dirKey,\n\t\t\t\t\tsize: 0,\n\t\t\t\t\tlastModified: new Date(),\n\t\t\t\t});\n\n\t\t\t\t// Filter by hidden\n\t\t\t\tif (!hidden && stat.name.startsWith('.')) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Filter by kind\n\t\t\t\tif (kind && stat.kind !== kind) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tresults.push(stat);\n\t\t\t}\n\n\t\t\t// Process objects (files) to convert to IFileStat\n\t\t\tconst seenDirs = new Set<string>();\n\t\t\tfor (const obj of objects) {\n\t\t\t\tthis.checkAborted(signal);\n\n\t\t\t\tconst key = obj.name;\n\t\t\t\tif (!key) continue;\n\n\t\t\t\t// Skip if not under our prefix\n\t\t\t\tif (prefixWithSlash && !key.startsWith(prefixWithSlash)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Strip the prefix from the key for path conversion\n\t\t\t\tconst relativeKey = prefixWithSlash ? key.slice(prefixWithSlash.length) : key;\n\n\t\t\t\t// Calculate depth: count the number of slashes in the relative path\n\t\t\t\t// depth=1 means immediate children (no slashes), depth=2 means one level deep (one slash), etc.\n\t\t\t\tconst depthLevel = (relativeKey.match(/\\//g) || []).length + 1;\n\n\t\t\t\t// Filter by depth\n\t\t\t\tif (depthLevel > depth) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst isDir = this.isDirectoryKey(key);\n\n\t\t\t\t// Track directories to avoid duplicates\n\t\t\t\tif (isDir) {\n\t\t\t\t\tconst dirKey = key.slice(0, -1);\n\t\t\t\t\tif (seenDirs.has(dirKey)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tseenDirs.add(dirKey);\n\t\t\t\t} else {\n\t\t\t\t\t// For files in recursive mode, always include them\n\t\t\t\t\t// For non-recursive mode, check if parent directory was already added\n\t\t\t\t\tif (!recursive) {\n\t\t\t\t\t\tconst parentDir = dirname(key).replace(/\\\\/g, '/') + '/';\n\t\t\t\t\t\tif (seenDirs.has(parentDir.slice(0, -1))) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst stat = this.toFileStat(key, {\n\t\t\t\t\tname: key,\n\t\t\t\t\tsize: obj.size || 0,\n\t\t\t\t\tlastModified: obj.lastModified,\n\t\t\t\t\tetag: obj.etag,\n\t\t\t\t});\n\n\t\t\t\t// Filter by hidden\n\t\t\t\tif (!hidden && stat.name.startsWith('.')) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Filter by kind\n\t\t\t\tif (kind && stat.kind !== kind) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tresults.push(stat);\n\t\t\t}\n\n\t\t\t// Handle recursive with depth > 1\n\t\t\tif (!recursive && depth > 1) {\n\t\t\t\tconst subdirs = results.filter((entry) => entry.kind === 'directory');\n\t\t\t\tfor (const subdir of subdirs) {\n\t\t\t\t\tthis.checkAborted(signal);\n\t\t\t\t\tconst maxDepth = depth - 1;\n\t\t\t\t\tif (maxDepth > 0) {\n\t\t\t\t\t\tconst subEntries = await this.readdir(subdir.path, {\n\t\t\t\t\t\t\t...options,\n\t\t\t\t\t\t\tdepth: maxDepth,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tresults = [...results, ...subEntries];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Handle glob filtering\n\t\t\tif (glob) {\n\t\t\t\tconst { matcher } = await import('micromatch');\n\t\t\t\tconst match = matcher(glob);\n\t\t\t\tresults = results.filter((entry) => match(entry.path));\n\t\t\t}\n\n\t\t\treturn results;\n\t\t} catch (error: any) {\n\t\t\tif (error.code === 'NoSuchKey' || error.message?.includes('404') || error.code === 'NotFound') {\n\t\t\t\tthrow new Error(`Directory not found: ${dir}`);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync stat(entry: string, options: StatOptions = {}): Promise<IFileStat> {\n\t\tconst { signal } = options;\n\t\tthis.checkAborted(signal);\n\n\t\tconst key = this.normalizeKey(entry);\n\t\tif (!key) {\n\t\t\t// Root directory\n\t\t\treturn {\n\t\t\t\tdirectory: '/',\n\t\t\t\tpath: '/',\n\t\t\t\tname: '/',\n\t\t\t\tkind: 'directory',\n\t\t\t\tmtime: Date.now(),\n\t\t\t\tsize: 0,\n\t\t\t\tmeta: {},\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\t// Try to get object stat\n\t\t\tconst stat = await this.client.statObject(this.bucket, key);\n\t\t\treturn this.toFileStat(key, {\n\t\t\t\tname: key,\n\t\t\t\tsize: stat.size,\n\t\t\t\tlastModified: stat.lastModified,\n\t\t\t\tetag: stat.etag,\n\t\t\t});\n\t\t} catch (error: any) {\n\t\t\t// If object not found, try checking if it's a directory\n\t\t\tif (error.code === 'NotFound' || error.code === 'NoSuchKey') {\n\t\t\t\tconst dirKey = key.endsWith('/') ? key : key + '/';\n\t\t\t\ttry {\n\t\t\t\t\t// List objects with this prefix to check if it's a directory\n\t\t\t\t\tconst objectStream = this.client.listObjects(this.bucket, dirKey, false);\n\t\t\t\t\tlet hasObjects = false;\n\n\t\t\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\t\t\tobjectStream.on('data', () => {\n\t\t\t\t\t\t\thasObjects = true;\n\t\t\t\t\t\t\tobjectStream.destroy();\n\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tobjectStream.on('end', () => {\n\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tobjectStream.on('error', reject);\n\n\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\tsignal.addEventListener('abort', () => {\n\t\t\t\t\t\t\t\tobjectStream.destroy();\n\t\t\t\t\t\t\t\treject(new Error('The operation was aborted'));\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tif (hasObjects) {\n\t\t\t\t\t\t// It's a directory\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tdirectory: this.getDirectory(key),\n\t\t\t\t\t\t\tpath: this.keyToPath(key),\n\t\t\t\t\t\t\tname: basename(key.replace(/\\/$/, '')) || '/',\n\t\t\t\t\t\t\tkind: 'directory',\n\t\t\t\t\t\t\tmtime: Date.now(),\n\t\t\t\t\t\t\tsize: 0,\n\t\t\t\t\t\t\tmeta: {},\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore listing errors\n\t\t\t\t}\n\n\t\t\t\tthrow new Error(`File not found: ${entry}`);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync mkdir(path: string, options: MkdirOptions = {}): Promise<void> {\n\t\tconst { recursive = false, signal } = options;\n\t\tthis.checkAborted(signal);\n\n\t\t// In S3, directories don't actually exist - they're just prefixes\n\t\t// Optionally create a marker object (empty object with trailing slash)\n\t\tconst key = this.normalizeKey(path);\n\t\tif (!key) {\n\t\t\treturn; // Root directory, nothing to do\n\t\t}\n\n\t\t// Ensure it ends with / to indicate directory\n\t\tconst dirKey = key.endsWith('/') ? key : key + '/';\n\n\t\t// Try to create a marker object (0-byte object)\n\t\ttry {\n\t\t\tconst stream = new PassThrough();\n\t\t\tstream.end();\n\t\t\tawait this.client.putObject(this.bucket, dirKey, stream, 0, {\n\t\t\t\t'Content-Type': 'application/x-directory',\n\t\t\t});\n\t\t} catch (error: any) {\n\t\t\t// If it already exists or we don't have permission, that's okay for mkdir\n\t\t\tif (error.code !== 'NoSuchBucket' && error.code !== 'AccessDenied') {\n\t\t\t\t// Ignore other errors for mkdir\n\t\t\t}\n\t\t}\n\t}\n\n\tasync readFile(path: string, options?: ReadFileOptions & { encoding: 'text' }): Promise<string>;\n\tasync readFile(path: string, options?: ReadFileOptions): Promise<Uint8Array>;\n\tasync readFile(path: string, options: ReadFileOptions = {}): Promise<string | Uint8Array> {\n\t\tconst { encoding = 'binary', signal, onDownloadProgress } = options;\n\t\tthis.checkAborted(signal);\n\n\t\tconst key = this.normalizeKey(path);\n\t\tif (!key) {\n\t\t\tthrow new Error('Cannot read root directory');\n\t\t}\n\n\t\ttry {\n\t\t\t// MinIO getObject returns Promise<Readable>\n\t\t\tconst nodeStream = await this.client.getObject(this.bucket, key);\n\t\t\tconst chunks: Buffer[] = [];\n\t\t\tlet loaded = 0;\n\t\t\tlet total = 0;\n\n\t\t\t// Get object size for progress if available\n\t\t\ttry {\n\t\t\t\tconst stat = await this.client.statObject(this.bucket, key);\n\t\t\t\ttotal = stat.size;\n\t\t\t} catch {\n\t\t\t\t// Ignore if stat fails\n\t\t\t}\n\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tnodeStream.on('data', (chunk: Buffer) => {\n\t\t\t\t\tchunks.push(chunk);\n\t\t\t\t\tloaded += chunk.length;\n\t\t\t\t\tif (onDownloadProgress) {\n\t\t\t\t\t\tonDownloadProgress({ loaded, total: total || -1 });\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tnodeStream.on('end', () => {\n\t\t\t\t\tconst buffer = Buffer.concat(chunks);\n\t\t\t\t\tif (encoding === 'text') {\n\t\t\t\t\t\tresolve(buffer.toString('utf-8'));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresolve(new Uint8Array(buffer));\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tnodeStream.on('error', reject);\n\n\t\t\t\tif (signal) {\n\t\t\t\t\tsignal.addEventListener('abort', () => {\n\t\t\t\t\t\tif (nodeStream.destroy) {\n\t\t\t\t\t\t\tnodeStream.destroy(new Error('The operation was aborted'));\n\t\t\t\t\t\t}\n\t\t\t\t\t\treject(new Error('The operation was aborted'));\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error: any) {\n\t\t\tif (error.code === 'NoSuchKey' || error.code === 'NotFound') {\n\t\t\t\tthrow new Error(`File not found: ${path}`);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync writeFile(\n\t\tpath: string,\n\t\tdata: string | ArrayBuffer | ArrayBufferView<ArrayBufferLike> | ReadableStream | Buffer | Readable,\n\t\toptions: WriteFileOptions = {},\n\t): Promise<void> {\n\t\tconst { signal, overwrite = true, onUploadProgress } = options;\n\t\tthis.checkAborted(signal);\n\n\t\tconst key = this.normalizeKey(path);\n\t\tif (!key) {\n\t\t\tthrow new Error('Cannot write to root directory');\n\t\t}\n\n\t\t// Check if file exists and overwrite is false\n\t\tif (!overwrite) {\n\t\t\tconst exists = await this.exists(path);\n\t\t\tif (exists) {\n\t\t\t\tthrow new Error(`File already exists: ${path}`);\n\t\t\t}\n\t\t}\n\n\t\t// Convert data to stream or buffer\n\t\tlet stream: Readable;\n\t\tlet size: number;\n\n\t\tif (data instanceof Readable) {\n\t\t\tstream = data;\n\t\t\tsize = 0; // Unknown size\n\t\t} else if (data instanceof ReadableStream) {\n\t\t\t// Convert Web ReadableStream to Node Readable\n\t\t\tstream = Readable.fromWeb(data as import('node:stream/web').ReadableStream);\n\t\t\tsize = 0;\n\t\t} else {\n\t\t\tlet buffer: Buffer;\n\t\t\tif (data instanceof ArrayBuffer) {\n\t\t\t\tbuffer = Buffer.from(data);\n\t\t\t} else if (Buffer.isBuffer(data)) {\n\t\t\t\tbuffer = data;\n\t\t\t} else if (typeof data === 'string') {\n\t\t\t\tbuffer = Buffer.from(data, 'utf-8');\n\t\t\t} else {\n\t\t\t\t// ArrayBufferView\n\t\t\t\tbuffer = Buffer.from(data.buffer, data.byteOffset, data.byteLength);\n\t\t\t}\n\n\t\t\tsize = buffer.length;\n\t\t\tstream = new Readable();\n\t\t\tstream.push(buffer);\n\t\t\tstream.push(null);\n\t\t}\n\n\t\t// Wrap stream for progress tracking if needed\n\t\tif (onUploadProgress) {\n\t\t\tlet loaded = 0;\n\t\t\tconst progressStream = new PassThrough();\n\t\t\tstream.on('data', (chunk: Buffer) => {\n\t\t\t\tloaded += chunk.length;\n\t\t\t\tonUploadProgress({ loaded, total: size || -1 });\n\t\t\t});\n\t\t\tstream.pipe(progressStream);\n\t\t\tstream = progressStream;\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.client.putObject(this.bucket, key, stream, size);\n\t\t} catch (error: any) {\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync rm(path: string, options: RmOptions = {}): Promise<void> {\n\t\tconst { recursive = false, force = false, signal } = options;\n\t\tthis.checkAborted(signal);\n\n\t\tconst key = this.normalizeKey(path);\n\t\tif (!key) {\n\t\t\tthrow new Error('Cannot remove root directory');\n\t\t}\n\n\t\ttry {\n\t\t\tif (recursive) {\n\t\t\t\t// List all objects with this prefix\n\t\t\t\tconst prefix = key.endsWith('/') ? key : key + '/';\n\t\t\t\tconst objectStream = this.client.listObjects(this.bucket, prefix, true);\n\t\t\t\tconst keys: string[] = [];\n\n\t\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\t\tobjectStream.on('data', (obj: any) => {\n\t\t\t\t\t\tif (obj.name) {\n\t\t\t\t\t\t\tkeys.push(obj.name);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tobjectStream.on('end', () => {\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t});\n\n\t\t\t\t\tobjectStream.on('error', reject);\n\n\t\t\t\t\tif (signal) {\n\t\t\t\t\t\tsignal.addEventListener('abort', () => {\n\t\t\t\t\t\t\tobjectStream.destroy();\n\t\t\t\t\t\t\treject(new Error('The operation was aborted'));\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t// Delete all objects\n\t\t\t\tif (keys.length > 0) {\n\t\t\t\t\tawait this.client.removeObjects(this.bucket, keys);\n\t\t\t\t}\n\n\t\t\t\t// Also delete the marker object if it exists\n\t\t\t\tconst markerKey = prefix;\n\t\t\t\ttry {\n\t\t\t\t\tawait this.client.removeObject(this.bucket, markerKey);\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore if marker doesn't exist\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Delete single object\n\t\t\t\ttry {\n\t\t\t\t\tawait this.client.removeObject(this.bucket, key);\n\t\t\t\t} catch (error: any) {\n\t\t\t\t\t// Check if it's a directory with files\n\t\t\t\t\tif (error.code === 'NoSuchKey' || error.code === 'NotFound') {\n\t\t\t\t\t\tconst prefix = key.endsWith('/') ? key : key + '/';\n\t\t\t\t\t\tconst objectStream = this.client.listObjects(this.bucket, prefix, false);\n\t\t\t\t\t\tlet hasObjects = false;\n\n\t\t\t\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\t\t\t\tobjectStream.on('data', () => {\n\t\t\t\t\t\t\t\thasObjects = true;\n\t\t\t\t\t\t\t\tobjectStream.destroy();\n\t\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tobjectStream.on('end', () => {\n\t\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tobjectStream.on('error', () => {\n\t\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (hasObjects) {\n\t\t\t\t\t\t\tif (!force) {\n\t\t\t\t\t\t\t\tthrow new Error('Directory not empty');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// If force, delete recursively\n\t\t\t\t\t\t\tconst recursiveStream = this.client.listObjects(this.bucket, prefix, true);\n\t\t\t\t\t\t\tconst keys: string[] = [];\n\t\t\t\t\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\t\t\t\t\trecursiveStream.on('data', (obj: any) => {\n\t\t\t\t\t\t\t\t\tif (obj.name) {\n\t\t\t\t\t\t\t\t\t\tkeys.push(obj.name);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\trecursiveStream.on('end', () => resolve());\n\t\t\t\t\t\t\t\trecursiveStream.on('error', () => resolve());\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (keys.length > 0) {\n\t\t\t\t\t\t\t\tawait this.client.removeObjects(this.bucket, keys);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Also try to remove the marker\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait this.client.removeObject(this.bucket, prefix);\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// Ignore\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// File doesn't exist\n\t\t\t\t\t\t\tif (!force) {\n\t\t\t\t\t\t\t\tthrow new Error('File not found');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// If force, just return without error\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (!force) {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error: any) {\n\t\t\tif (force && (error.code === 'NoSuchKey' || error.code === 'NotFound')) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (force && error.message === 'File not found') {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync rename(oldPath: string, newPath: string, options: RenameOptions = {}): Promise<void> {\n\t\tconst { signal, overwrite = false } = options;\n\t\tthis.checkAborted(signal);\n\n\t\tconst oldKey = this.normalizeKey(oldPath);\n\t\tconst newKey = this.normalizeKey(newPath);\n\n\t\tif (!oldKey) {\n\t\t\tthrow new Error('Cannot rename root directory');\n\t\t}\n\n\t\t// Check if target exists and overwrite is false\n\t\tif (!overwrite) {\n\t\t\tconst exists = await this.exists(newPath);\n\t\t\tif (exists) {\n\t\t\t\tthrow new Error(`Destination already exists: ${newPath}`);\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\t// Check if it's a directory (has objects with prefix)\n\t\t\tconst isDir = oldKey.endsWith('/');\n\t\t\tconst prefix = isDir ? oldKey : oldKey + '/';\n\n\t\t\tconst objectStream = this.client.listObjects(this.bucket, prefix, true);\n\t\t\tconst objects: Array<{ name: string }> = [];\n\n\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\tobjectStream.on('data', (obj: any) => {\n\t\t\t\t\tif (obj.name) {\n\t\t\t\t\t\tobjects.push({ name: obj.name });\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tobjectStream.on('end', () => {\n\t\t\t\t\tresolve();\n\t\t\t\t});\n\n\t\t\t\tobjectStream.on('error', reject);\n\n\t\t\t\tif (signal) {\n\t\t\t\t\tsignal.addEventListener('abort', () => {\n\t\t\t\t\t\tobjectStream.destroy();\n\t\t\t\t\t\treject(new Error('The operation was aborted'));\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (objects.length > 0) {\n\t\t\t\t// It's a directory or has multiple objects, move all\n\t\t\t\tconst newPrefix = newKey.endsWith('/') ? newKey : newKey + '/';\n\n\t\t\t\t// Move all objects\n\t\t\t\tawait Promise.all(\n\t\t\t\t\tobjects.map(async (obj) => {\n\t\t\t\t\t\tconst objKey = obj.name;\n\t\t\t\t\t\tif (!objKey) return;\n\n\t\t\t\t\t\tconst relativeKey = objKey.slice(prefix.length);\n\t\t\t\t\t\tconst newObjKey = newPrefix + relativeKey;\n\n\t\t\t\t\t\t// Copy then delete\n\t\t\t\t\t\t// MinIO copyObject signature: copyObject(bucketName, objectName, sourceObject)\n\t\t\t\t\t\t// sourceObject should be a string in format \"bucket/object\"\n\t\t\t\t\t\tawait this.client.copyObject(this.bucket, newObjKey, `${this.bucket}/${objKey}`);\n\t\t\t\t\t\tawait this.client.removeObject(this.bucket, objKey);\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\t// Move marker object if it exists (skip if it's a directory marker with data)\n\t\t\t\ttry {\n\t\t\t\t\t// Check if it's a directory marker (ends with /)\n\t\t\t\t\tif (prefix.endsWith('/')) {\n\t\t\t\t\t\t// Try to copy the marker, but skip if it fails due to \"contains data payload\"\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait this.client.copyObject(this.bucket, newPrefix, `${this.bucket}/${prefix}`);\n\t\t\t\t\t\t\tawait this.client.removeObject(this.bucket, prefix);\n\t\t\t\t\t\t} catch (error: any) {\n\t\t\t\t\t\t\t// If error is about data payload, just remove the old marker\n\t\t\t\t\t\t\t// Directory markers are optional in S3\n\t\t\t\t\t\t\tif (error.message?.includes('data payload') || error.code === 'InvalidRequest') {\n\t\t\t\t\t\t\t\tawait this.client.removeObject(this.bucket, prefix);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait this.client.copyObject(this.bucket, newPrefix, `${this.bucket}/${prefix}`);\n\t\t\t\t\t\tawait this.client.removeObject(this.bucket, prefix);\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore if marker doesn't exist\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Single file - copy then delete\n\t\t\t\tawait this.client.copyObject(this.bucket, newKey, `${this.bucket}/${oldKey}`);\n\t\t\t\tawait this.client.removeObject(this.bucket, oldKey);\n\t\t\t}\n\t\t} catch (error: any) {\n\t\t\tif (error.code === 'NoSuchKey' || error.code === 'NotFound') {\n\t\t\t\tthrow new Error(`Source file not found: ${oldPath}`);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync exists(path: string): Promise<boolean> {\n\t\ttry {\n\t\t\tconst key = this.normalizeKey(path);\n\t\t\tif (!key) {\n\t\t\t\treturn true; // Root always exists\n\t\t\t}\n\n\t\t\tawait this.client.statObject(this.bucket, key);\n\t\t\treturn true;\n\t\t} catch (error: any) {\n\t\t\tif (error.code === 'NotFound' || error.code === 'NoSuchKey') {\n\t\t\t\t// Check if it's a directory\n\t\t\t\tconst key = this.normalizeKey(path);\n\t\t\t\tconst dirKey = key.endsWith('/') ? key : key + '/';\n\t\t\t\ttry {\n\t\t\t\t\tconst objectStream = this.client.listObjects(this.bucket, dirKey, false);\n\t\t\t\t\tlet hasObjects = false;\n\n\t\t\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\t\t\tobjectStream.on('data', () => {\n\t\t\t\t\t\t\thasObjects = true;\n\t\t\t\t\t\t\tobjectStream.destroy();\n\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tobjectStream.on('end', () => {\n\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tobjectStream.on('error', () => {\n\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\t\treturn hasObjects;\n\t\t\t\t} catch {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tasync copy(src: string, dest: string, options: CopyOptions = {}): Promise<void> {\n\t\tconst { signal, overwrite = true, shallow = false } = options;\n\t\tthis.checkAborted(signal);\n\n\t\tconst srcKey = this.normalizeKey(src);\n\t\tconst destKey = this.normalizeKey(dest);\n\n\t\tif (!srcKey) {\n\t\t\tthrow new Error('Cannot copy root directory');\n\t\t}\n\n\t\t// Check if source exists\n\t\ttry {\n\t\t\tconst srcStat = await this.stat(src);\n\n\t\t\t// Check if destination exists and overwrite is false\n\t\t\tif (!overwrite) {\n\t\t\t\tconst exists = await this.exists(dest);\n\t\t\t\tif (exists) {\n\t\t\t\t\tthrow new Error(`Destination already exists: ${dest}`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (srcStat.kind === 'directory') {\n\t\t\t\t// Copy directory recursively\n\t\t\t\tconst srcPrefix = srcKey.endsWith('/') ? srcKey : srcKey + '/';\n\t\t\t\tconst destPrefix = destKey.endsWith('/') ? destKey : destKey + '/';\n\n\t\t\t\tconst objectStream = this.client.listObjects(this.bucket, srcPrefix, !shallow);\n\t\t\t\tconst objects: Array<{ name: string }> = [];\n\n\t\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\t\tobjectStream.on('data', (obj: any) => {\n\t\t\t\t\t\tif (obj.name) {\n\t\t\t\t\t\t\tobjects.push({ name: obj.name });\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tobjectStream.on('end', () => {\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t});\n\n\t\t\t\t\tobjectStream.on('error', reject);\n\n\t\t\t\t\tif (signal) {\n\t\t\t\t\t\tsignal.addEventListener('abort', () => {\n\t\t\t\t\t\t\tobjectStream.destroy();\n\t\t\t\t\t\t\treject(new Error('The operation was aborted'));\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t// Copy all objects\n\t\t\t\tawait Promise.all(\n\t\t\t\t\tobjects.map(async (obj: { name: string }) => {\n\t\t\t\t\t\tconst objKey = obj.name;\n\t\t\t\t\t\tif (!objKey) return;\n\n\t\t\t\t\t\tconst relativeKey = objKey.slice(srcPrefix.length);\n\t\t\t\t\t\tconst newObjKey = destPrefix + relativeKey;\n\n\t\t\t\t\t\tawait this.client.copyObject(this.bucket, newObjKey, `${this.bucket}/${objKey}`);\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\t// Copy marker object if it exists (skip if it's a directory marker with data)\n\t\t\t\ttry {\n\t\t\t\t\t// Check if it's a directory marker (ends with /)\n\t\t\t\t\tif (srcPrefix.endsWith('/')) {\n\t\t\t\t\t\t// Try to copy the marker, but skip if it fails due to \"contains data payload\"\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait this.client.copyObject(this.bucket, destPrefix, `${this.bucket}/${srcPrefix}`);\n\t\t\t\t\t\t} catch (error: any) {\n\t\t\t\t\t\t\t// If error is about data payload, just skip copying the marker\n\t\t\t\t\t\t\t// Directory markers are optional in S3\n\t\t\t\t\t\t\tif (!error.message?.includes('data payload') && error.code !== 'InvalidRequest') {\n\t\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait this.client.copyObject(this.bucket, destPrefix, `${this.bucket}/${srcPrefix}`);\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore if marker doesn't exist\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Copy single file\n\t\t\t\tawait this.client.copyObject(this.bucket, destKey, `${this.bucket}/${srcKey}`);\n\t\t\t}\n\t\t} catch (error: any) {\n\t\t\tif (error.code === 'NoSuchKey' || error.code === 'NotFound') {\n\t\t\t\tthrow new Error(`Source file not found: ${src}`);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tcreateReadStream(path: string, options: CreateReadStreamOptions = {}): Readable {\n\t\tconst key = this.normalizeKey(path);\n\t\tif (!key) {\n\t\t\tthrow new Error('Cannot read root directory');\n\t\t}\n\n\t\tconst { range, signal } = options;\n\n\t\t// MinIO getObject and getPartialObject both return Promise<Readable>\n\t\t// Create a Readable stream that waits for the promise to resolve\n\t\tconst client = this.client;\n\t\tconst bucket = this.bucket;\n\t\tconst readable = new Readable({\n\t\t\tasync read() {\n\t\t\t\t// Only initialize once\n\t\t\t\tif ((readable as any)._initialized) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t(readable as any)._initialized = true;\n\n\t\t\t\ttry {\n\t\t\t\t\tlet nodeStream: Readable;\n\n\t\t\t\t\tif (range) {\n\t\t\t\t\t\t// Use getPartialObject for range requests\n\t\t\t\t\t\t// getPartialObject's length parameter: number of bytes to read (not end position)\n\t\t\t\t\t\t// So for range {start: 0, end: 4}, we need length = end - start + 1 = 5\n\t\t\t\t\t\tconst length = range.end !== undefined ? range.end - range.start + 1 : undefined;\n\t\t\t\t\t\tnodeStream = await client.getPartialObject(bucket, key, range.start, length);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnodeStream = await client.getObject(bucket, key);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Pipe the actual stream to our readable\n\t\t\t\t\tnodeStream.on('data', (chunk) => {\n\t\t\t\t\t\tif (!readable.push(chunk)) {\n\t\t\t\t\t\t\t// If push returns false, the stream is backpressured\n\t\t\t\t\t\t\tnodeStream.pause();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tnodeStream.on('end', () => {\n\t\t\t\t\t\treadable.push(null);\n\t\t\t\t\t});\n\n\t\t\t\t\tnodeStream.on('error', (err) => {\n\t\t\t\t\t\treadable.emit('error', err);\n\t\t\t\t\t});\n\n\t\t\t\t\tif (signal) {\n\t\t\t\t\t\tsignal.addEventListener('abort', () => {\n\t\t\t\t\t\t\tif (nodeStream.destroy) {\n\t\t\t\t\t\t\t\tnodeStream.destroy(new Error('The operation was aborted'));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treadable.emit('error', new Error('The operation was aborted'));\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} catch (error: any) {\n\t\t\t\t\treadable.emit('error', error);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\n\t\treturn readable;\n\t}\n\n\tcreateReadableStream(path: string, options: CreateReadStreamOptions = {}): ReadableStream {\n\t\tconst key = this.normalizeKey(path);\n\t\tif (!key) {\n\t\t\tthrow new Error('Cannot read root directory');\n\t\t}\n\n\t\tconst { range, signal } = options;\n\n\t\t// MinIO getObject and getPartialObject both return Promise<Readable>\n\t\tconst client = this.client;\n\t\tconst bucket = this.bucket;\n\t\treturn new ReadableStream({\n\t\t\tasync start(controller) {\n\t\t\t\ttry {\n\t\t\t\t\tlet nodeStream: Readable;\n\n\t\t\t\t\tif (range) {\n\t\t\t\t\t\t// Use getPartialObject for range requests\n\t\t\t\t\t\t// getPartialObject's length parameter: number of bytes to read (not end position)\n\t\t\t\t\t\t// So for range {start: 0, end: 4}, we need length = end - start + 1 = 5\n\t\t\t\t\t\tconst length = range.end !== undefined ? range.end - range.start + 1 : undefined;\n\t\t\t\t\t\tnodeStream = await client.getPartialObject(bucket, key, range.start, length);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnodeStream = await client.getObject(bucket, key);\n\t\t\t\t\t}\n\n\t\t\t\t\tnodeStream.on('data', (chunk) => {\n\t\t\t\t\t\tcontroller.enqueue(chunk);\n\t\t\t\t\t});\n\n\t\t\t\t\tnodeStream.on('end', () => {\n\t\t\t\t\t\tcontroller.close();\n\t\t\t\t\t});\n\n\t\t\t\t\tnodeStream.on('error', (err) => {\n\t\t\t\t\t\tcontroller.error(err);\n\t\t\t\t\t});\n\n\t\t\t\t\tif (signal) {\n\t\t\t\t\t\tsignal.addEventListener('abort', () => {\n\t\t\t\t\t\t\tif (nodeStream.destroy) {\n\t\t\t\t\t\t\t\tnodeStream.destroy(new Error('The operation was aborted'));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontroller.error(new Error('The operation was aborted'));\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} catch (error: any) {\n\t\t\t\t\tcontroller.error(error);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t}\n\n\tcreateWriteStream(path: string, options?: CreateWriteStreamOptions): Writable {\n\t\tthrow new Error('Not implemented');\n\t}\n\n\tcreateWritableStream(path: string, options: CreateWriteStreamOptions = {}): WritableStream {\n\t\tconst key = this.normalizeKey(path);\n\t\tif (!key) {\n\t\t\tthrow new Error('Cannot write to root directory');\n\t\t}\n\n\t\tconst { signal, overwrite = true } = options;\n\t\tthis.checkAborted(signal);\n\n\t\t// Create a WritableStream that buffers data and uploads when done\n\t\tconst buffer: Uint8Array[] = [];\n\t\tlet controller: WritableStreamDefaultController;\n\t\tconst client = this.client;\n\t\tconst bucket = this.bucket;\n\t\tconst checkAborted = this.checkAborted.bind(this);\n\n\t\treturn new WritableStream({\n\t\t\tstart(ctrl) {\n\t\t\t\tcontroller = ctrl;\n\t\t\t},\n\t\t\tasync write(chunk) {\n\t\t\t\tbuffer.push(chunk);\n\t\t\t},\n\t\t\tasync close() {\n\t\t\t\ttry {\n\t\t\t\t\tcheckAborted(signal);\n\t\t\t\t\tconst data = Buffer.concat(buffer.map((chunk) => Buffer.from(chunk)));\n\t\t\t\t\tconst stream = new Readable();\n\t\t\t\t\tstream.push(data);\n\t\t\t\t\tstream.push(null);\n\t\t\t\t\tawait client.putObject(bucket, key, stream, data.length);\n\t\t\t\t\t// Controller closes automatically when close() completes successfully\n\t\t\t\t} catch (error) {\n\t\t\t\t\tcontroller.error(error);\n\t\t\t\t}\n\t\t\t},\n\t\t\tabort(reason) {\n\t\t\t\tbuffer.length = 0;\n\t\t\t\tcontroller.error(reason);\n\t\t\t},\n\t\t});\n\t}\n\n\tgetUrl(path: IFileStat | string, options?: any): string | undefined {\n\t\tif (typeof path === 'object' && path?.kind !== 'file') {\n\t\t\treturn;\n\t\t}\n\t\tconst key = typeof path === 'string' ? this.normalizeKey(path) : this.normalizeKey(path.path);\n\t\tif (!key) {\n\t\t\treturn;\n\t\t}\n\n\t\t// MinIO supports presigned URLs, but getUrl is synchronous\n\t\t// We can't generate presigned URLs synchronously, so return undefined\n\t\t// For presigned URLs, users should use a separate method or await the promise\n\t\treturn undefined;\n\t}\n}\n"],"names":["basename","dirname","normalize","PassThrough","Readable","parseS3Url","Client","createMinioFileSystem","options","parsed","Error","client","prefix","endpoint","bucket","minioClient","endPoint","port","useSSL","useSsl","accessKey","accessKeyId","secretKey","secretAccessKey","region","pathStyle","normalizedPrefix","replace","MinioFS","normalizeKey","path","normalized","stripPrefix","key","startsWith","withoutPrefix","slice","length","keyToPath","getDirectory","dir","isDirectoryKey","endsWith","toFileStat","obj","isDir","directory","name","kind","mtime","lastModified","Date","getTime","now","size","meta","etag","checkAborted","signal","aborted","readdir","glob","recursive","depth","hidden","dirPrefix","prefixWithSlash","objects","commonPrefixes","objectStream","listObjects","Promise","resolve","reject","on","push","err","addEventListener","destroy","results","relativePrefix","dirName","firstSlash","indexOf","dirKey","stat","seenDirs","Set","relativeKey","depthLevel","match","has","add","parentDir","subdirs","filter","entry","subdir","maxDepth","subEntries","matcher","error","code","message","includes","statObject","hasObjects","mkdir","stream","end","putObject","readFile","encoding","onDownloadProgress","nodeStream","getObject","chunks","loaded","total","chunk","buffer","Buffer","concat","toString","Uint8Array","writeFile","data","overwrite","onUploadProgress","exists","ReadableStream","fromWeb","ArrayBuffer","from","isBuffer","byteOffset","byteLength","progressStream","pipe","rm","force","keys","removeObjects","markerKey","removeObject","recursiveStream","rename","oldPath","newPath","oldKey","newKey","newPrefix","all","map","objKey","newObjKey","copyObject","copy","src","dest","shallow","srcKey","destKey","srcStat","srcPrefix","destPrefix","createReadStream","range","readable","read","_initialized","undefined","start","getPartialObject","pause","emit","createReadableStream","controller","enqueue","close","createWriteStream","createWritableStream","bind","WritableStream","ctrl","write","abort","reason","getUrl"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,OAAO,EAAEC,SAAS,QAAQ,QAAQ;AACrD,SAASC,WAAW,EAAEC,QAAQ,QAAuB,cAAc;AACnE,SAASC,UAAU,QAAgC,mBAAmB;AACtE,SAASC,MAAM,QAAQ,QAAQ;AA2B/B,OAAO,SAASC,sBAAsBC,UAAwC,CAAC,CAAC;IAC/E,MAAMC,SAASJ,WAAWG;IAC1B,IAAI,CAACC,QAAQ;QACZ,MAAM,IAAIC,MAAM;IACjB;IAEA,MAAM,EAAEC,MAAM,EAAEC,MAAM,EAAE,GAAGJ;IAC3B,IAAI,CAACG,UAAW,CAAA,CAACF,OAAOI,QAAQ,IAAI,CAACJ,OAAOK,MAAM,AAAD,GAAI;QACpD,MAAM,IAAIJ,MAAM;IACjB;IAEA,IAAIK;IACJ,IAAID;IAEJ,IAAIH,QAAQ;QACXI,cAAcJ;QACdG,SAASL,OAAOK,MAAM,IAAI;IAC3B,OAAO;QACNA,SAASL,OAAOK,MAAM,IAAI;QAE1B,iEAAiE;QACjEC,cAAc,IAAIT,OAAO;YACxBU,UAAUP,OAAOI,QAAQ;YACzBI,MAAMR,OAAOQ,IAAI;YACjBC,QAAQT,OAAOU,MAAM,IAAI;YACzBC,WAAWX,OAAOY,WAAW,IAAI;YACjCC,WAAWb,OAAOc,eAAe,IAAI;YACrCC,QAAQf,OAAOe,MAAM;YACrBC,WAAWhB,OAAOgB,SAAS;QAC5B;IACD;IAEA,oDAAoD;IACpD,MAAMC,mBAAmBd,SAASA,OAAOe,OAAO,CAAC,QAAQ,IAAIA,OAAO,CAAC,QAAQ,MAAM;IAEnF,OAAO,IAAIC,QAAQb,aAAaD,QAAQY;AACzC;AAEA,IAAA,AAAME,UAAN,MAAMA;;;;IACL,YACC,AAAiBjB,MAAc,EAC/B,AAAiBG,MAAc,EAC/B,AAAiBF,SAAiB,EAAE,CACnC;aAHgBD,SAAAA;aACAG,SAAAA;aACAF,SAAAA;IACf;IAEH;;;EAGC,GACD,AAAQiB,aAAaC,IAAY,EAAU;QAC1C,IAAI,CAACA,QAAQA,SAAS,KAAK;YAC1B,OAAO,IAAI,CAAClB,MAAM;QACnB;QACA,MAAMmB,aAAa7B,UAAU4B,MAAMH,OAAO,CAAC,QAAQ,IAAIA,OAAO,CAAC,OAAO;QAEtE,wBAAwB;QACxB,IAAI,IAAI,CAACf,MAAM,EAAE;YAChB,OAAO,IAAI,CAACA,MAAM,GAAG,MAAMmB;QAC5B;QACA,OAAOA;IACR;IAEA;;EAEC,GACD,AAAQC,YAAYC,GAAW,EAAU;QACxC,IAAI,CAACA,KAAK;YACT,OAAO;QACR;QACA,oEAAoE;QACpE,IAAI,IAAI,CAACrB,MAAM,IAAIqB,QAAQ,IAAI,CAACrB,MAAM,EAAE;YACvC,OAAO;QACR;QACA,IAAI,CAAC,IAAI,CAACA,MAAM,IAAI,CAACqB,IAAIC,UAAU,CAAC,IAAI,CAACtB,MAAM,GAAG,MAAM;YACvD,OAAOqB,IAAIC,UAAU,CAAC,OAAOD,MAAM,MAAMA;QAC1C;QACA,MAAME,gBAAgBF,IAAIG,KAAK,CAAC,IAAI,CAACxB,MAAM,CAACyB,MAAM;QAClD,OAAOF,iBAAiB;IACzB;IAEA;;EAEC,GACD,AAAQG,UAAUL,GAAW,EAAU;QACtC,IAAI,CAACA,KAAK;YACT,OAAO;QACR;QACA,OAAO,IAAI,CAACD,WAAW,CAACC;IACzB;IAEA;;EAEC,GACD,AAAQM,aAAaN,GAAW,EAAU;QACzC,IAAI,CAACA,KAAK;YACT,OAAO;QACR;QACA,MAAMO,MAAMvC,QAAQgC,KAAKN,OAAO,CAAC,OAAO;QACxC,OAAOa,QAAQ,MAAM,MAAM,MAAMA;IAClC;IAEA;;EAEC,GACD,AAAQC,eAAeR,GAAW,EAAW;QAC5C,OAAOA,IAAIS,QAAQ,CAAC;IACrB;IAEA;;EAEC,GACD,AAAQC,WAAWV,GAAW,EAAEW,GAAsE,EAAa;QAClH,MAAMC,QAAQ,IAAI,CAACJ,cAAc,CAACR;QAClC,MAAMH,OAAO,IAAI,CAACQ,SAAS,CAACL;QAC5B,MAAMa,YAAY,IAAI,CAACP,YAAY,CAACN;QAEpC,OAAO;YACNa;YACAhB;YACAiB,MAAMF,QAAQ7C,SAASiC,IAAIG,KAAK,CAAC,GAAG,CAAC,OAAOpC,SAAS8C,cAAc,MAAM9C,SAASiC;YAClFe,MAAMH,QAAQ,cAAc;YAC5BI,OAAOL,IAAIM,YAAY,GAAG,IAAIC,KAAKP,IAAIM,YAAY,EAAEE,OAAO,KAAKD,KAAKE,GAAG;YACzEC,MAAMV,IAAIU,IAAI,IAAI;YAClBC,MAAM;gBACL,GAAIX,IAAIY,IAAI,GAAG;oBAAEA,MAAMZ,IAAIY,IAAI,CAAC7B,OAAO,CAAC,MAAM;gBAAI,IAAI,CAAC,CAAC;YACzD;QACD;IACD;IAEQ8B,aAAaC,MAAoB,EAAQ;QAChD,IAAIA,QAAQC,SAAS;YACpB,MAAM,IAAIjD,MAAM;QACjB;IACD;IAEA,MAAMkD,QAAQpB,GAAW,EAAEhC,UAA0B,CAAC,CAAC,EAAwB;QAC9E,MAAM,EAAEqD,IAAI,EAAEC,SAAS,EAAEC,QAAQ,CAAC,EAAEf,IAAI,EAAEgB,SAAS,IAAI,EAAEN,MAAM,EAAE,GAAGlD;QACpE,IAAI,CAACiD,YAAY,CAACC;QAElB,MAAMO,YAAY,IAAI,CAACpC,YAAY,CAACW;QACpC,MAAM0B,kBAAkBD,YAAaA,UAAUvB,QAAQ,CAAC,OAAOuB,YAAYA,YAAY,MAAO;QAE9F,IAAI;YACH,8CAA8C;YAC9C,qFAAqF;YACrF,MAAME,UAAoG,EAAE;YAC5G,MAAMC,iBAA2B,EAAE;YAEnC,qCAAqC;YACrC,8EAA8E;YAC9E,MAAMC,eAAe,IAAI,CAAC1D,MAAM,CAAC2D,WAAW,CAAC,IAAI,CAACxD,MAAM,EAAEoD,iBAAiBJ;YAE3E,MAAM,IAAIS,QAAc,CAACC,SAASC;gBACjCJ,aAAaK,EAAE,CAAC,QAAQ,CAAC9B;oBACxB,IAAIA,IAAIG,IAAI,EAAE;wBACboB,QAAQQ,IAAI,CAAC;4BACZ5B,MAAMH,IAAIG,IAAI;4BACdO,MAAMV,IAAIU,IAAI,IAAI;4BAClBJ,cAAcN,IAAIM,YAAY,IAAI,IAAIC;4BACtCK,MAAMZ,IAAIY,IAAI,IAAI;wBACnB;oBACD,OAAO,IAAIZ,IAAIhC,MAAM,EAAE;wBACtB,4BAA4B;wBAC5BwD,eAAeO,IAAI,CAAC/B,IAAIhC,MAAM;oBAC/B;gBACD;gBAEAyD,aAAaK,EAAE,CAAC,OAAO;oBACtBF;gBACD;gBAEAH,aAAaK,EAAE,CAAC,SAAS,CAACE;oBACzBH,OAAOG;gBACR;gBAEA,IAAIlB,QAAQ;oBACXA,OAAOmB,gBAAgB,CAAC,SAAS;wBAChCR,aAAaS,OAAO;wBACpBL,OAAO,IAAI/D,MAAM;oBAClB;gBACD;YACD;YAEA,IAAIqE,UAAuB,EAAE;YAE7B,6CAA6C;YAC7C,KAAK,MAAMnE,UAAUwD,eAAgB;gBACpC,IAAI,CAACX,YAAY,CAACC;gBAElB,+BAA+B;gBAC/B,IAAIQ,mBAAmB,CAACtD,OAAOsB,UAAU,CAACgC,kBAAkB;oBAC3D;gBACD;gBAEA,oBAAoB;gBACpB,MAAMc,iBAAiBd,kBAAkBtD,OAAOwB,KAAK,CAAC8B,gBAAgB7B,MAAM,IAAIzB;gBAChF,MAAMqE,UAAUD,eAAerD,OAAO,CAAC,OAAO,KAAK,wBAAwB;gBAE3E,IAAI,CAACsD,SAAS;gBAEd,kDAAkD;gBAClD,IAAI,CAACnB,aAAaC,UAAU,GAAG;oBAC9B,MAAMmB,aAAaD,QAAQE,OAAO,CAAC;oBACnC,IAAID,cAAc,GAAG;wBACpB;oBACD;gBACD;gBAEA,MAAME,SAASxE,OAAO8B,QAAQ,CAAC,OAAO9B,SAASA,SAAS;gBACxD,MAAMyE,OAAO,IAAI,CAAC1C,UAAU,CAACyC,QAAQ;oBACpCrC,MAAMqC;oBACN9B,MAAM;oBACNJ,cAAc,IAAIC;gBACnB;gBAEA,mBAAmB;gBACnB,IAAI,CAACa,UAAUqB,KAAKtC,IAAI,CAACb,UAAU,CAAC,MAAM;oBACzC;gBACD;gBAEA,iBAAiB;gBACjB,IAAIc,QAAQqC,KAAKrC,IAAI,KAAKA,MAAM;oBAC/B;gBACD;gBAEA+B,QAAQJ,IAAI,CAACU;YACd;YAEA,kDAAkD;YAClD,MAAMC,WAAW,IAAIC;YACrB,KAAK,MAAM3C,OAAOuB,QAAS;gBAC1B,IAAI,CAACV,YAAY,CAACC;gBAElB,MAAMzB,MAAMW,IAAIG,IAAI;gBACpB,IAAI,CAACd,KAAK;gBAEV,+BAA+B;gBAC/B,IAAIiC,mBAAmB,CAACjC,IAAIC,UAAU,CAACgC,kBAAkB;oBACxD;gBACD;gBAEA,oDAAoD;gBACpD,MAAMsB,cAActB,kBAAkBjC,IAAIG,KAAK,CAAC8B,gBAAgB7B,MAAM,IAAIJ;gBAE1E,oEAAoE;gBACpE,gGAAgG;gBAChG,MAAMwD,aAAa,AAACD,CAAAA,YAAYE,KAAK,CAAC,UAAU,EAAE,AAAD,EAAGrD,MAAM,GAAG;gBAE7D,kBAAkB;gBAClB,IAAIoD,aAAa1B,OAAO;oBACvB;gBACD;gBAEA,MAAMlB,QAAQ,IAAI,CAACJ,cAAc,CAACR;gBAElC,wCAAwC;gBACxC,IAAIY,OAAO;oBACV,MAAMuC,SAASnD,IAAIG,KAAK,CAAC,GAAG,CAAC;oBAC7B,IAAIkD,SAASK,GAAG,CAACP,SAAS;wBACzB;oBACD;oBACAE,SAASM,GAAG,CAACR;gBACd,OAAO;oBACN,mDAAmD;oBACnD,sEAAsE;oBACtE,IAAI,CAACtB,WAAW;wBACf,MAAM+B,YAAY5F,QAAQgC,KAAKN,OAAO,CAAC,OAAO,OAAO;wBACrD,IAAI2D,SAASK,GAAG,CAACE,UAAUzD,KAAK,CAAC,GAAG,CAAC,KAAK;4BACzC;wBACD;oBACD;gBACD;gBAEA,MAAMiD,OAAO,IAAI,CAAC1C,UAAU,CAACV,KAAK;oBACjCc,MAAMd;oBACNqB,MAAMV,IAAIU,IAAI,IAAI;oBAClBJ,cAAcN,IAAIM,YAAY;oBAC9BM,MAAMZ,IAAIY,IAAI;gBACf;gBAEA,mBAAmB;gBACnB,IAAI,CAACQ,UAAUqB,KAAKtC,IAAI,CAACb,UAAU,CAAC,MAAM;oBACzC;gBACD;gBAEA,iBAAiB;gBACjB,IAAIc,QAAQqC,KAAKrC,IAAI,KAAKA,MAAM;oBAC/B;gBACD;gBAEA+B,QAAQJ,IAAI,CAACU;YACd;YAEA,kCAAkC;YAClC,IAAI,CAACvB,aAAaC,QAAQ,GAAG;gBAC5B,MAAM+B,UAAUf,QAAQgB,MAAM,CAAC,CAACC,QAAUA,MAAMhD,IAAI,KAAK;gBACzD,KAAK,MAAMiD,UAAUH,QAAS;oBAC7B,IAAI,CAACrC,YAAY,CAACC;oBAClB,MAAMwC,WAAWnC,QAAQ;oBACzB,IAAImC,WAAW,GAAG;wBACjB,MAAMC,aAAa,MAAM,IAAI,CAACvC,OAAO,CAACqC,OAAOnE,IAAI,EAAE;4BAClD,GAAGtB,OAAO;4BACVuD,OAAOmC;wBACR;wBACAnB,UAAU;+BAAIA;+BAAYoB;yBAAW;oBACtC;gBACD;YACD;YAEA,wBAAwB;YACxB,IAAItC,MAAM;gBACT,MAAM,EAAEuC,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC;gBACjC,MAAMV,QAAQU,QAAQvC;gBACtBkB,UAAUA,QAAQgB,MAAM,CAAC,CAACC,QAAUN,MAAMM,MAAMlE,IAAI;YACrD;YAEA,OAAOiD;QACR,EAAE,OAAOsB,OAAY;YACpB,IAAIA,MAAMC,IAAI,KAAK,eAAeD,MAAME,OAAO,EAAEC,SAAS,UAAUH,MAAMC,IAAI,KAAK,YAAY;gBAC9F,MAAM,IAAI5F,MAAM,CAAC,qBAAqB,EAAE8B,KAAK;YAC9C;YACA,MAAM6D;QACP;IACD;IAEA,MAAMhB,KAAKW,KAAa,EAAExF,UAAuB,CAAC,CAAC,EAAsB;QACxE,MAAM,EAAEkD,MAAM,EAAE,GAAGlD;QACnB,IAAI,CAACiD,YAAY,CAACC;QAElB,MAAMzB,MAAM,IAAI,CAACJ,YAAY,CAACmE;QAC9B,IAAI,CAAC/D,KAAK;YACT,iBAAiB;YACjB,OAAO;gBACNa,WAAW;gBACXhB,MAAM;gBACNiB,MAAM;gBACNC,MAAM;gBACNC,OAAOE,KAAKE,GAAG;gBACfC,MAAM;gBACNC,MAAM,CAAC;YACR;QACD;QAEA,IAAI;YACH,yBAAyB;YACzB,MAAM8B,OAAO,MAAM,IAAI,CAAC1E,MAAM,CAAC8F,UAAU,CAAC,IAAI,CAAC3F,MAAM,EAAEmB;YACvD,OAAO,IAAI,CAACU,UAAU,CAACV,KAAK;gBAC3Bc,MAAMd;gBACNqB,MAAM+B,KAAK/B,IAAI;gBACfJ,cAAcmC,KAAKnC,YAAY;gBAC/BM,MAAM6B,KAAK7B,IAAI;YAChB;QACD,EAAE,OAAO6C,OAAY;YACpB,wDAAwD;YACxD,IAAIA,MAAMC,IAAI,KAAK,cAAcD,MAAMC,IAAI,KAAK,aAAa;gBAC5D,MAAMlB,SAASnD,IAAIS,QAAQ,CAAC,OAAOT,MAAMA,MAAM;gBAC/C,IAAI;oBACH,6DAA6D;oBAC7D,MAAMoC,eAAe,IAAI,CAAC1D,MAAM,CAAC2D,WAAW,CAAC,IAAI,CAACxD,MAAM,EAAEsE,QAAQ;oBAClE,IAAIsB,aAAa;oBAEjB,MAAM,IAAInC,QAAc,CAACC,SAASC;wBACjCJ,aAAaK,EAAE,CAAC,QAAQ;4BACvBgC,aAAa;4BACbrC,aAAaS,OAAO;4BACpBN;wBACD;wBAEAH,aAAaK,EAAE,CAAC,OAAO;4BACtBF;wBACD;wBAEAH,aAAaK,EAAE,CAAC,SAASD;wBAEzB,IAAIf,QAAQ;4BACXA,OAAOmB,gBAAgB,CAAC,SAAS;gCAChCR,aAAaS,OAAO;gCACpBL,OAAO,IAAI/D,MAAM;4BAClB;wBACD;oBACD;oBAEA,IAAIgG,YAAY;wBACf,mBAAmB;wBACnB,OAAO;4BACN5D,WAAW,IAAI,CAACP,YAAY,CAACN;4BAC7BH,MAAM,IAAI,CAACQ,SAAS,CAACL;4BACrBc,MAAM/C,SAASiC,IAAIN,OAAO,CAAC,OAAO,QAAQ;4BAC1CqB,MAAM;4BACNC,OAAOE,KAAKE,GAAG;4BACfC,MAAM;4BACNC,MAAM,CAAC;wBACR;oBACD;gBACD,EAAE,OAAM;gBACP,wBAAwB;gBACzB;gBAEA,MAAM,IAAI7C,MAAM,CAAC,gBAAgB,EAAEsF,OAAO;YAC3C;YACA,MAAMK;QACP;IACD;IAEA,MAAMM,MAAM7E,IAAY,EAAEtB,UAAwB,CAAC,CAAC,EAAiB;QACpE,MAAM,EAAEsD,YAAY,KAAK,EAAEJ,MAAM,EAAE,GAAGlD;QACtC,IAAI,CAACiD,YAAY,CAACC;QAElB,kEAAkE;QAClE,uEAAuE;QACvE,MAAMzB,MAAM,IAAI,CAACJ,YAAY,CAACC;QAC9B,IAAI,CAACG,KAAK;YACT,QAAQ,gCAAgC;QACzC;QAEA,8CAA8C;QAC9C,MAAMmD,SAASnD,IAAIS,QAAQ,CAAC,OAAOT,MAAMA,MAAM;QAE/C,gDAAgD;QAChD,IAAI;YACH,MAAM2E,SAAS,IAAIzG;YACnByG,OAAOC,GAAG;YACV,MAAM,IAAI,CAAClG,MAAM,CAACmG,SAAS,CAAC,IAAI,CAAChG,MAAM,EAAEsE,QAAQwB,QAAQ,GAAG;gBAC3D,gBAAgB;YACjB;QACD,EAAE,OAAOP,OAAY;YACpB,0EAA0E;YAC1E,IAAIA,MAAMC,IAAI,KAAK,kBAAkBD,MAAMC,IAAI,KAAK,gBAAgB;YACnE,gCAAgC;YACjC;QACD;IACD;IAIA,MAAMS,SAASjF,IAAY,EAAEtB,UAA2B,CAAC,CAAC,EAAgC;QACzF,MAAM,EAAEwG,WAAW,QAAQ,EAAEtD,MAAM,EAAEuD,kBAAkB,EAAE,GAAGzG;QAC5D,IAAI,CAACiD,YAAY,CAACC;QAElB,MAAMzB,MAAM,IAAI,CAACJ,YAAY,CAACC;QAC9B,IAAI,CAACG,KAAK;YACT,MAAM,IAAIvB,MAAM;QACjB;QAEA,IAAI;YACH,4CAA4C;YAC5C,MAAMwG,aAAa,MAAM,IAAI,CAACvG,MAAM,CAACwG,SAAS,CAAC,IAAI,CAACrG,MAAM,EAAEmB;YAC5D,MAAMmF,SAAmB,EAAE;YAC3B,IAAIC,SAAS;YACb,IAAIC,QAAQ;YAEZ,4CAA4C;YAC5C,IAAI;gBACH,MAAMjC,OAAO,MAAM,IAAI,CAAC1E,MAAM,CAAC8F,UAAU,CAAC,IAAI,CAAC3F,MAAM,EAAEmB;gBACvDqF,QAAQjC,KAAK/B,IAAI;YAClB,EAAE,OAAM;YACP,uBAAuB;YACxB;YAEA,OAAO,IAAIiB,QAAQ,CAACC,SAASC;gBAC5ByC,WAAWxC,EAAE,CAAC,QAAQ,CAAC6C;oBACtBH,OAAOzC,IAAI,CAAC4C;oBACZF,UAAUE,MAAMlF,MAAM;oBACtB,IAAI4E,oBAAoB;wBACvBA,mBAAmB;4BAAEI;4BAAQC,OAAOA,SAAS,CAAC;wBAAE;oBACjD;gBACD;gBAEAJ,WAAWxC,EAAE,CAAC,OAAO;oBACpB,MAAM8C,SAASC,OAAOC,MAAM,CAACN;oBAC7B,IAAIJ,aAAa,QAAQ;wBACxBxC,QAAQgD,OAAOG,QAAQ,CAAC;oBACzB,OAAO;wBACNnD,QAAQ,IAAIoD,WAAWJ;oBACxB;gBACD;gBAEAN,WAAWxC,EAAE,CAAC,SAASD;gBAEvB,IAAIf,QAAQ;oBACXA,OAAOmB,gBAAgB,CAAC,SAAS;wBAChC,IAAIqC,WAAWpC,OAAO,EAAE;4BACvBoC,WAAWpC,OAAO,CAAC,IAAIpE,MAAM;wBAC9B;wBACA+D,OAAO,IAAI/D,MAAM;oBAClB;gBACD;YACD;QACD,EAAE,OAAO2F,OAAY;YACpB,IAAIA,MAAMC,IAAI,KAAK,eAAeD,MAAMC,IAAI,KAAK,YAAY;gBAC5D,MAAM,IAAI5F,MAAM,CAAC,gBAAgB,EAAEoB,MAAM;YAC1C;YACA,MAAMuE;QACP;IACD;IAEA,MAAMwB,UACL/F,IAAY,EACZgG,IAAkG,EAClGtH,UAA4B,CAAC,CAAC,EACd;QAChB,MAAM,EAAEkD,MAAM,EAAEqE,YAAY,IAAI,EAAEC,gBAAgB,EAAE,GAAGxH;QACvD,IAAI,CAACiD,YAAY,CAACC;QAElB,MAAMzB,MAAM,IAAI,CAACJ,YAAY,CAACC;QAC9B,IAAI,CAACG,KAAK;YACT,MAAM,IAAIvB,MAAM;QACjB;QAEA,8CAA8C;QAC9C,IAAI,CAACqH,WAAW;YACf,MAAME,SAAS,MAAM,IAAI,CAACA,MAAM,CAACnG;YACjC,IAAImG,QAAQ;gBACX,MAAM,IAAIvH,MAAM,CAAC,qBAAqB,EAAEoB,MAAM;YAC/C;QACD;QAEA,mCAAmC;QACnC,IAAI8E;QACJ,IAAItD;QAEJ,IAAIwE,gBAAgB1H,UAAU;YAC7BwG,SAASkB;YACTxE,OAAO,GAAG,eAAe;QAC1B,OAAO,IAAIwE,gBAAgBI,gBAAgB;YAC1C,8CAA8C;YAC9CtB,SAASxG,SAAS+H,OAAO,CAACL;YAC1BxE,OAAO;QACR,OAAO;YACN,IAAIkE;YACJ,IAAIM,gBAAgBM,aAAa;gBAChCZ,SAASC,OAAOY,IAAI,CAACP;YACtB,OAAO,IAAIL,OAAOa,QAAQ,CAACR,OAAO;gBACjCN,SAASM;YACV,OAAO,IAAI,OAAOA,SAAS,UAAU;gBACpCN,SAASC,OAAOY,IAAI,CAACP,MAAM;YAC5B,OAAO;gBACN,kBAAkB;gBAClBN,SAASC,OAAOY,IAAI,CAACP,KAAKN,MAAM,EAAEM,KAAKS,UAAU,EAAET,KAAKU,UAAU;YACnE;YAEAlF,OAAOkE,OAAOnF,MAAM;YACpBuE,SAAS,IAAIxG;YACbwG,OAAOjC,IAAI,CAAC6C;YACZZ,OAAOjC,IAAI,CAAC;QACb;QAEA,8CAA8C;QAC9C,IAAIqD,kBAAkB;YACrB,IAAIX,SAAS;YACb,MAAMoB,iBAAiB,IAAItI;YAC3ByG,OAAOlC,EAAE,CAAC,QAAQ,CAAC6C;gBAClBF,UAAUE,MAAMlF,MAAM;gBACtB2F,iBAAiB;oBAAEX;oBAAQC,OAAOhE,QAAQ,CAAC;gBAAE;YAC9C;YACAsD,OAAO8B,IAAI,CAACD;YACZ7B,SAAS6B;QACV;QAEA,IAAI;YACH,MAAM,IAAI,CAAC9H,MAAM,CAACmG,SAAS,CAAC,IAAI,CAAChG,MAAM,EAAEmB,KAAK2E,QAAQtD;QACvD,EAAE,OAAO+C,OAAY;YACpB,MAAMA;QACP;IACD;IAEA,MAAMsC,GAAG7G,IAAY,EAAEtB,UAAqB,CAAC,CAAC,EAAiB;QAC9D,MAAM,EAAEsD,YAAY,KAAK,EAAE8E,QAAQ,KAAK,EAAElF,MAAM,EAAE,GAAGlD;QACrD,IAAI,CAACiD,YAAY,CAACC;QAElB,MAAMzB,MAAM,IAAI,CAACJ,YAAY,CAACC;QAC9B,IAAI,CAACG,KAAK;YACT,MAAM,IAAIvB,MAAM;QACjB;QAEA,IAAI;YACH,IAAIoD,WAAW;gBACd,oCAAoC;gBACpC,MAAMlD,SAASqB,IAAIS,QAAQ,CAAC,OAAOT,MAAMA,MAAM;gBAC/C,MAAMoC,eAAe,IAAI,CAAC1D,MAAM,CAAC2D,WAAW,CAAC,IAAI,CAACxD,MAAM,EAAEF,QAAQ;gBAClE,MAAMiI,OAAiB,EAAE;gBAEzB,MAAM,IAAItE,QAAc,CAACC,SAASC;oBACjCJ,aAAaK,EAAE,CAAC,QAAQ,CAAC9B;wBACxB,IAAIA,IAAIG,IAAI,EAAE;4BACb8F,KAAKlE,IAAI,CAAC/B,IAAIG,IAAI;wBACnB;oBACD;oBAEAsB,aAAaK,EAAE,CAAC,OAAO;wBACtBF;oBACD;oBAEAH,aAAaK,EAAE,CAAC,SAASD;oBAEzB,IAAIf,QAAQ;wBACXA,OAAOmB,gBAAgB,CAAC,SAAS;4BAChCR,aAAaS,OAAO;4BACpBL,OAAO,IAAI/D,MAAM;wBAClB;oBACD;gBACD;gBAEA,qBAAqB;gBACrB,IAAImI,KAAKxG,MAAM,GAAG,GAAG;oBACpB,MAAM,IAAI,CAAC1B,MAAM,CAACmI,aAAa,CAAC,IAAI,CAAChI,MAAM,EAAE+H;gBAC9C;gBAEA,6CAA6C;gBAC7C,MAAME,YAAYnI;gBAClB,IAAI;oBACH,MAAM,IAAI,CAACD,MAAM,CAACqI,YAAY,CAAC,IAAI,CAAClI,MAAM,EAAEiI;gBAC7C,EAAE,OAAM;gBACP,iCAAiC;gBAClC;YACD,OAAO;gBACN,uBAAuB;gBACvB,IAAI;oBACH,MAAM,IAAI,CAACpI,MAAM,CAACqI,YAAY,CAAC,IAAI,CAAClI,MAAM,EAAEmB;gBAC7C,EAAE,OAAOoE,OAAY;oBACpB,uCAAuC;oBACvC,IAAIA,MAAMC,IAAI,KAAK,eAAeD,MAAMC,IAAI,KAAK,YAAY;wBAC5D,MAAM1F,SAASqB,IAAIS,QAAQ,CAAC,OAAOT,MAAMA,MAAM;wBAC/C,MAAMoC,eAAe,IAAI,CAAC1D,MAAM,CAAC2D,WAAW,CAAC,IAAI,CAACxD,MAAM,EAAEF,QAAQ;wBAClE,IAAI8F,aAAa;wBAEjB,MAAM,IAAInC,QAAc,CAACC;4BACxBH,aAAaK,EAAE,CAAC,QAAQ;gCACvBgC,aAAa;gCACbrC,aAAaS,OAAO;gCACpBN;4BACD;4BAEAH,aAAaK,EAAE,CAAC,OAAO;gCACtBF;4BACD;4BAEAH,aAAaK,EAAE,CAAC,SAAS;gCACxBF;4BACD;wBACD;wBAEA,IAAIkC,YAAY;4BACf,IAAI,CAACkC,OAAO;gCACX,MAAM,IAAIlI,MAAM;4BACjB;4BACA,+BAA+B;4BAC/B,MAAMuI,kBAAkB,IAAI,CAACtI,MAAM,CAAC2D,WAAW,CAAC,IAAI,CAACxD,MAAM,EAAEF,QAAQ;4BACrE,MAAMiI,OAAiB,EAAE;4BACzB,MAAM,IAAItE,QAAc,CAACC;gCACxByE,gBAAgBvE,EAAE,CAAC,QAAQ,CAAC9B;oCAC3B,IAAIA,IAAIG,IAAI,EAAE;wCACb8F,KAAKlE,IAAI,CAAC/B,IAAIG,IAAI;oCACnB;gCACD;gCACAkG,gBAAgBvE,EAAE,CAAC,OAAO,IAAMF;gCAChCyE,gBAAgBvE,EAAE,CAAC,SAAS,IAAMF;4BACnC;4BACA,IAAIqE,KAAKxG,MAAM,GAAG,GAAG;gCACpB,MAAM,IAAI,CAAC1B,MAAM,CAACmI,aAAa,CAAC,IAAI,CAAChI,MAAM,EAAE+H;4BAC9C;4BACA,gCAAgC;4BAChC,IAAI;gCACH,MAAM,IAAI,CAAClI,MAAM,CAACqI,YAAY,CAAC,IAAI,CAAClI,MAAM,EAAEF;4BAC7C,EAAE,OAAM;4BACP,SAAS;4BACV;wBACD,OAAO;4BACN,qBAAqB;4BACrB,IAAI,CAACgI,OAAO;gCACX,MAAM,IAAIlI,MAAM;4BACjB;4BACA,sCAAsC;4BACtC;wBACD;oBACD,OAAO,IAAI,CAACkI,OAAO;wBAClB,MAAMvC;oBACP;gBACD;YACD;QACD,EAAE,OAAOA,OAAY;YACpB,IAAIuC,SAAUvC,CAAAA,MAAMC,IAAI,KAAK,eAAeD,MAAMC,IAAI,KAAK,UAAS,GAAI;gBACvE;YACD;YACA,IAAIsC,SAASvC,MAAME,OAAO,KAAK,kBAAkB;gBAChD;YACD;YACA,MAAMF;QACP;IACD;IAEA,MAAM6C,OAAOC,OAAe,EAAEC,OAAe,EAAE5I,UAAyB,CAAC,CAAC,EAAiB;QAC1F,MAAM,EAAEkD,MAAM,EAAEqE,YAAY,KAAK,EAAE,GAAGvH;QACtC,IAAI,CAACiD,YAAY,CAACC;QAElB,MAAM2F,SAAS,IAAI,CAACxH,YAAY,CAACsH;QACjC,MAAMG,SAAS,IAAI,CAACzH,YAAY,CAACuH;QAEjC,IAAI,CAACC,QAAQ;YACZ,MAAM,IAAI3I,MAAM;QACjB;QAEA,gDAAgD;QAChD,IAAI,CAACqH,WAAW;YACf,MAAME,SAAS,MAAM,IAAI,CAACA,MAAM,CAACmB;YACjC,IAAInB,QAAQ;gBACX,MAAM,IAAIvH,MAAM,CAAC,4BAA4B,EAAE0I,SAAS;YACzD;QACD;QAEA,IAAI;YACH,sDAAsD;YACtD,MAAMvG,QAAQwG,OAAO3G,QAAQ,CAAC;YAC9B,MAAM9B,SAASiC,QAAQwG,SAASA,SAAS;YAEzC,MAAMhF,eAAe,IAAI,CAAC1D,MAAM,CAAC2D,WAAW,CAAC,IAAI,CAACxD,MAAM,EAAEF,QAAQ;YAClE,MAAMuD,UAAmC,EAAE;YAE3C,MAAM,IAAII,QAAc,CAACC,SAASC;gBACjCJ,aAAaK,EAAE,CAAC,QAAQ,CAAC9B;oBACxB,IAAIA,IAAIG,IAAI,EAAE;wBACboB,QAAQQ,IAAI,CAAC;4BAAE5B,MAAMH,IAAIG,IAAI;wBAAC;oBAC/B;gBACD;gBAEAsB,aAAaK,EAAE,CAAC,OAAO;oBACtBF;gBACD;gBAEAH,aAAaK,EAAE,CAAC,SAASD;gBAEzB,IAAIf,QAAQ;oBACXA,OAAOmB,gBAAgB,CAAC,SAAS;wBAChCR,aAAaS,OAAO;wBACpBL,OAAO,IAAI/D,MAAM;oBAClB;gBACD;YACD;YAEA,IAAIyD,QAAQ9B,MAAM,GAAG,GAAG;gBACvB,qDAAqD;gBACrD,MAAMkH,YAAYD,OAAO5G,QAAQ,CAAC,OAAO4G,SAASA,SAAS;gBAE3D,mBAAmB;gBACnB,MAAM/E,QAAQiF,GAAG,CAChBrF,QAAQsF,GAAG,CAAC,OAAO7G;oBAClB,MAAM8G,SAAS9G,IAAIG,IAAI;oBACvB,IAAI,CAAC2G,QAAQ;oBAEb,MAAMlE,cAAckE,OAAOtH,KAAK,CAACxB,OAAOyB,MAAM;oBAC9C,MAAMsH,YAAYJ,YAAY/D;oBAE9B,mBAAmB;oBACnB,+EAA+E;oBAC/E,4DAA4D;oBAC5D,MAAM,IAAI,CAAC7E,MAAM,CAACiJ,UAAU,CAAC,IAAI,CAAC9I,MAAM,EAAE6I,WAAW,GAAG,IAAI,CAAC7I,MAAM,CAAC,CAAC,EAAE4I,QAAQ;oBAC/E,MAAM,IAAI,CAAC/I,MAAM,CAACqI,YAAY,CAAC,IAAI,CAAClI,MAAM,EAAE4I;gBAC7C;gBAGD,8EAA8E;gBAC9E,IAAI;oBACH,iDAAiD;oBACjD,IAAI9I,OAAO8B,QAAQ,CAAC,MAAM;wBACzB,8EAA8E;wBAC9E,IAAI;4BACH,MAAM,IAAI,CAAC/B,MAAM,CAACiJ,UAAU,CAAC,IAAI,CAAC9I,MAAM,EAAEyI,WAAW,GAAG,IAAI,CAACzI,MAAM,CAAC,CAAC,EAAEF,QAAQ;4BAC/E,MAAM,IAAI,CAACD,MAAM,CAACqI,YAAY,CAAC,IAAI,CAAClI,MAAM,EAAEF;wBAC7C,EAAE,OAAOyF,OAAY;4BACpB,6DAA6D;4BAC7D,uCAAuC;4BACvC,IAAIA,MAAME,OAAO,EAAEC,SAAS,mBAAmBH,MAAMC,IAAI,KAAK,kBAAkB;gCAC/E,MAAM,IAAI,CAAC3F,MAAM,CAACqI,YAAY,CAAC,IAAI,CAAClI,MAAM,EAAEF;4BAC7C,OAAO;gCACN,MAAMyF;4BACP;wBACD;oBACD,OAAO;wBACN,MAAM,IAAI,CAAC1F,MAAM,CAACiJ,UAAU,CAAC,IAAI,CAAC9I,MAAM,EAAEyI,WAAW,GAAG,IAAI,CAACzI,MAAM,CAAC,CAAC,EAAEF,QAAQ;wBAC/E,MAAM,IAAI,CAACD,MAAM,CAACqI,YAAY,CAAC,IAAI,CAAClI,MAAM,EAAEF;oBAC7C;gBACD,EAAE,OAAM;gBACP,iCAAiC;gBAClC;YACD,OAAO;gBACN,iCAAiC;gBACjC,MAAM,IAAI,CAACD,MAAM,CAACiJ,UAAU,CAAC,IAAI,CAAC9I,MAAM,EAAEwI,QAAQ,GAAG,IAAI,CAACxI,MAAM,CAAC,CAAC,EAAEuI,QAAQ;gBAC5E,MAAM,IAAI,CAAC1I,MAAM,CAACqI,YAAY,CAAC,IAAI,CAAClI,MAAM,EAAEuI;YAC7C;QACD,EAAE,OAAOhD,OAAY;YACpB,IAAIA,MAAMC,IAAI,KAAK,eAAeD,MAAMC,IAAI,KAAK,YAAY;gBAC5D,MAAM,IAAI5F,MAAM,CAAC,uBAAuB,EAAEyI,SAAS;YACpD;YACA,MAAM9C;QACP;IACD;IAEA,MAAM4B,OAAOnG,IAAY,EAAoB;QAC5C,IAAI;YACH,MAAMG,MAAM,IAAI,CAACJ,YAAY,CAACC;YAC9B,IAAI,CAACG,KAAK;gBACT,OAAO,MAAM,qBAAqB;YACnC;YAEA,MAAM,IAAI,CAACtB,MAAM,CAAC8F,UAAU,CAAC,IAAI,CAAC3F,MAAM,EAAEmB;YAC1C,OAAO;QACR,EAAE,OAAOoE,OAAY;YACpB,IAAIA,MAAMC,IAAI,KAAK,cAAcD,MAAMC,IAAI,KAAK,aAAa;gBAC5D,4BAA4B;gBAC5B,MAAMrE,MAAM,IAAI,CAACJ,YAAY,CAACC;gBAC9B,MAAMsD,SAASnD,IAAIS,QAAQ,CAAC,OAAOT,MAAMA,MAAM;gBAC/C,IAAI;oBACH,MAAMoC,eAAe,IAAI,CAAC1D,MAAM,CAAC2D,WAAW,CAAC,IAAI,CAACxD,MAAM,EAAEsE,QAAQ;oBAClE,IAAIsB,aAAa;oBAEjB,MAAM,IAAInC,QAAc,CAACC;wBACxBH,aAAaK,EAAE,CAAC,QAAQ;4BACvBgC,aAAa;4BACbrC,aAAaS,OAAO;4BACpBN;wBACD;wBAEAH,aAAaK,EAAE,CAAC,OAAO;4BACtBF;wBACD;wBAEAH,aAAaK,EAAE,CAAC,SAAS;4BACxBF;wBACD;oBACD;oBAEA,OAAOkC;gBACR,EAAE,OAAM;oBACP,OAAO;gBACR;YACD;YACA,OAAO;QACR;IACD;IAEA,MAAMmD,KAAKC,GAAW,EAAEC,IAAY,EAAEvJ,UAAuB,CAAC,CAAC,EAAiB;QAC/E,MAAM,EAAEkD,MAAM,EAAEqE,YAAY,IAAI,EAAEiC,UAAU,KAAK,EAAE,GAAGxJ;QACtD,IAAI,CAACiD,YAAY,CAACC;QAElB,MAAMuG,SAAS,IAAI,CAACpI,YAAY,CAACiI;QACjC,MAAMI,UAAU,IAAI,CAACrI,YAAY,CAACkI;QAElC,IAAI,CAACE,QAAQ;YACZ,MAAM,IAAIvJ,MAAM;QACjB;QAEA,yBAAyB;QACzB,IAAI;YACH,MAAMyJ,UAAU,MAAM,IAAI,CAAC9E,IAAI,CAACyE;YAEhC,qDAAqD;YACrD,IAAI,CAAC/B,WAAW;gBACf,MAAME,SAAS,MAAM,IAAI,CAACA,MAAM,CAAC8B;gBACjC,IAAI9B,QAAQ;oBACX,MAAM,IAAIvH,MAAM,CAAC,4BAA4B,EAAEqJ,MAAM;gBACtD;YACD;YAEA,IAAII,QAAQnH,IAAI,KAAK,aAAa;gBACjC,6BAA6B;gBAC7B,MAAMoH,YAAYH,OAAOvH,QAAQ,CAAC,OAAOuH,SAASA,SAAS;gBAC3D,MAAMI,aAAaH,QAAQxH,QAAQ,CAAC,OAAOwH,UAAUA,UAAU;gBAE/D,MAAM7F,eAAe,IAAI,CAAC1D,MAAM,CAAC2D,WAAW,CAAC,IAAI,CAACxD,MAAM,EAAEsJ,WAAW,CAACJ;gBACtE,MAAM7F,UAAmC,EAAE;gBAE3C,MAAM,IAAII,QAAc,CAACC,SAASC;oBACjCJ,aAAaK,EAAE,CAAC,QAAQ,CAAC9B;wBACxB,IAAIA,IAAIG,IAAI,EAAE;4BACboB,QAAQQ,IAAI,CAAC;gCAAE5B,MAAMH,IAAIG,IAAI;4BAAC;wBAC/B;oBACD;oBAEAsB,aAAaK,EAAE,CAAC,OAAO;wBACtBF;oBACD;oBAEAH,aAAaK,EAAE,CAAC,SAASD;oBAEzB,IAAIf,QAAQ;wBACXA,OAAOmB,gBAAgB,CAAC,SAAS;4BAChCR,aAAaS,OAAO;4BACpBL,OAAO,IAAI/D,MAAM;wBAClB;oBACD;gBACD;gBAEA,mBAAmB;gBACnB,MAAM6D,QAAQiF,GAAG,CAChBrF,QAAQsF,GAAG,CAAC,OAAO7G;oBAClB,MAAM8G,SAAS9G,IAAIG,IAAI;oBACvB,IAAI,CAAC2G,QAAQ;oBAEb,MAAMlE,cAAckE,OAAOtH,KAAK,CAACgI,UAAU/H,MAAM;oBACjD,MAAMsH,YAAYU,aAAa7E;oBAE/B,MAAM,IAAI,CAAC7E,MAAM,CAACiJ,UAAU,CAAC,IAAI,CAAC9I,MAAM,EAAE6I,WAAW,GAAG,IAAI,CAAC7I,MAAM,CAAC,CAAC,EAAE4I,QAAQ;gBAChF;gBAGD,8EAA8E;gBAC9E,IAAI;oBACH,iDAAiD;oBACjD,IAAIU,UAAU1H,QAAQ,CAAC,MAAM;wBAC5B,8EAA8E;wBAC9E,IAAI;4BACH,MAAM,IAAI,CAAC/B,MAAM,CAACiJ,UAAU,CAAC,IAAI,CAAC9I,MAAM,EAAEuJ,YAAY,GAAG,IAAI,CAACvJ,MAAM,CAAC,CAAC,EAAEsJ,WAAW;wBACpF,EAAE,OAAO/D,OAAY;4BACpB,+DAA+D;4BAC/D,uCAAuC;4BACvC,IAAI,CAACA,MAAME,OAAO,EAAEC,SAAS,mBAAmBH,MAAMC,IAAI,KAAK,kBAAkB;gCAChF,MAAMD;4BACP;wBACD;oBACD,OAAO;wBACN,MAAM,IAAI,CAAC1F,MAAM,CAACiJ,UAAU,CAAC,IAAI,CAAC9I,MAAM,EAAEuJ,YAAY,GAAG,IAAI,CAACvJ,MAAM,CAAC,CAAC,EAAEsJ,WAAW;oBACpF;gBACD,EAAE,OAAM;gBACP,iCAAiC;gBAClC;YACD,OAAO;gBACN,mBAAmB;gBACnB,MAAM,IAAI,CAACzJ,MAAM,CAACiJ,UAAU,CAAC,IAAI,CAAC9I,MAAM,EAAEoJ,SAAS,GAAG,IAAI,CAACpJ,MAAM,CAAC,CAAC,EAAEmJ,QAAQ;YAC9E;QACD,EAAE,OAAO5D,OAAY;YACpB,IAAIA,MAAMC,IAAI,KAAK,eAAeD,MAAMC,IAAI,KAAK,YAAY;gBAC5D,MAAM,IAAI5F,MAAM,CAAC,uBAAuB,EAAEoJ,KAAK;YAChD;YACA,MAAMzD;QACP;IACD;IAEAiE,iBAAiBxI,IAAY,EAAEtB,UAAmC,CAAC,CAAC,EAAY;QAC/E,MAAMyB,MAAM,IAAI,CAACJ,YAAY,CAACC;QAC9B,IAAI,CAACG,KAAK;YACT,MAAM,IAAIvB,MAAM;QACjB;QAEA,MAAM,EAAE6J,KAAK,EAAE7G,MAAM,EAAE,GAAGlD;QAE1B,qEAAqE;QACrE,iEAAiE;QACjE,MAAMG,SAAS,IAAI,CAACA,MAAM;QAC1B,MAAMG,SAAS,IAAI,CAACA,MAAM;QAC1B,MAAM0J,WAAW,IAAIpK,SAAS;YAC7B,MAAMqK;gBACL,uBAAuB;gBACvB,IAAI,AAACD,SAAiBE,YAAY,EAAE;oBACnC;gBACD;gBACCF,SAAiBE,YAAY,GAAG;gBAEjC,IAAI;oBACH,IAAIxD;oBAEJ,IAAIqD,OAAO;wBACV,0CAA0C;wBAC1C,kFAAkF;wBAClF,wEAAwE;wBACxE,MAAMlI,SAASkI,MAAM1D,GAAG,KAAK8D,YAAYJ,MAAM1D,GAAG,GAAG0D,MAAMK,KAAK,GAAG,IAAID;wBACvEzD,aAAa,MAAMvG,OAAOkK,gBAAgB,CAAC/J,QAAQmB,KAAKsI,MAAMK,KAAK,EAAEvI;oBACtE,OAAO;wBACN6E,aAAa,MAAMvG,OAAOwG,SAAS,CAACrG,QAAQmB;oBAC7C;oBAEA,yCAAyC;oBACzCiF,WAAWxC,EAAE,CAAC,QAAQ,CAAC6C;wBACtB,IAAI,CAACiD,SAAS7F,IAAI,CAAC4C,QAAQ;4BAC1B,qDAAqD;4BACrDL,WAAW4D,KAAK;wBACjB;oBACD;oBAEA5D,WAAWxC,EAAE,CAAC,OAAO;wBACpB8F,SAAS7F,IAAI,CAAC;oBACf;oBAEAuC,WAAWxC,EAAE,CAAC,SAAS,CAACE;wBACvB4F,SAASO,IAAI,CAAC,SAASnG;oBACxB;oBAEA,IAAIlB,QAAQ;wBACXA,OAAOmB,gBAAgB,CAAC,SAAS;4BAChC,IAAIqC,WAAWpC,OAAO,EAAE;gCACvBoC,WAAWpC,OAAO,CAAC,IAAIpE,MAAM;4BAC9B;4BACA8J,SAASO,IAAI,CAAC,SAAS,IAAIrK,MAAM;wBAClC;oBACD;gBACD,EAAE,OAAO2F,OAAY;oBACpBmE,SAASO,IAAI,CAAC,SAAS1E;gBACxB;YACD;QACD;QAEA,OAAOmE;IACR;IAEAQ,qBAAqBlJ,IAAY,EAAEtB,UAAmC,CAAC,CAAC,EAAkB;QACzF,MAAMyB,MAAM,IAAI,CAACJ,YAAY,CAACC;QAC9B,IAAI,CAACG,KAAK;YACT,MAAM,IAAIvB,MAAM;QACjB;QAEA,MAAM,EAAE6J,KAAK,EAAE7G,MAAM,EAAE,GAAGlD;QAE1B,qEAAqE;QACrE,MAAMG,SAAS,IAAI,CAACA,MAAM;QAC1B,MAAMG,SAAS,IAAI,CAACA,MAAM;QAC1B,OAAO,IAAIoH,eAAe;YACzB,MAAM0C,OAAMK,UAAU;gBACrB,IAAI;oBACH,IAAI/D;oBAEJ,IAAIqD,OAAO;wBACV,0CAA0C;wBAC1C,kFAAkF;wBAClF,wEAAwE;wBACxE,MAAMlI,SAASkI,MAAM1D,GAAG,KAAK8D,YAAYJ,MAAM1D,GAAG,GAAG0D,MAAMK,KAAK,GAAG,IAAID;wBACvEzD,aAAa,MAAMvG,OAAOkK,gBAAgB,CAAC/J,QAAQmB,KAAKsI,MAAMK,KAAK,EAAEvI;oBACtE,OAAO;wBACN6E,aAAa,MAAMvG,OAAOwG,SAAS,CAACrG,QAAQmB;oBAC7C;oBAEAiF,WAAWxC,EAAE,CAAC,QAAQ,CAAC6C;wBACtB0D,WAAWC,OAAO,CAAC3D;oBACpB;oBAEAL,WAAWxC,EAAE,CAAC,OAAO;wBACpBuG,WAAWE,KAAK;oBACjB;oBAEAjE,WAAWxC,EAAE,CAAC,SAAS,CAACE;wBACvBqG,WAAW5E,KAAK,CAACzB;oBAClB;oBAEA,IAAIlB,QAAQ;wBACXA,OAAOmB,gBAAgB,CAAC,SAAS;4BAChC,IAAIqC,WAAWpC,OAAO,EAAE;gCACvBoC,WAAWpC,OAAO,CAAC,IAAIpE,MAAM;4BAC9B;4BACAuK,WAAW5E,KAAK,CAAC,IAAI3F,MAAM;wBAC5B;oBACD;gBACD,EAAE,OAAO2F,OAAY;oBACpB4E,WAAW5E,KAAK,CAACA;gBAClB;YACD;QACD;IACD;IAEA+E,kBAAkBtJ,IAAY,EAAEtB,OAAkC,EAAY;QAC7E,MAAM,IAAIE,MAAM;IACjB;IAEA2K,qBAAqBvJ,IAAY,EAAEtB,UAAoC,CAAC,CAAC,EAAkB;QAC1F,MAAMyB,MAAM,IAAI,CAACJ,YAAY,CAACC;QAC9B,IAAI,CAACG,KAAK;YACT,MAAM,IAAIvB,MAAM;QACjB;QAEA,MAAM,EAAEgD,MAAM,EAAEqE,YAAY,IAAI,EAAE,GAAGvH;QACrC,IAAI,CAACiD,YAAY,CAACC;QAElB,kEAAkE;QAClE,MAAM8D,SAAuB,EAAE;QAC/B,IAAIyD;QACJ,MAAMtK,SAAS,IAAI,CAACA,MAAM;QAC1B,MAAMG,SAAS,IAAI,CAACA,MAAM;QAC1B,MAAM2C,eAAe,IAAI,CAACA,YAAY,CAAC6H,IAAI,CAAC,IAAI;QAEhD,OAAO,IAAIC,eAAe;YACzBX,OAAMY,IAAI;gBACTP,aAAaO;YACd;YACA,MAAMC,OAAMlE,KAAK;gBAChBC,OAAO7C,IAAI,CAAC4C;YACb;YACA,MAAM4D;gBACL,IAAI;oBACH1H,aAAaC;oBACb,MAAMoE,OAAOL,OAAOC,MAAM,CAACF,OAAOiC,GAAG,CAAC,CAAClC,QAAUE,OAAOY,IAAI,CAACd;oBAC7D,MAAMX,SAAS,IAAIxG;oBACnBwG,OAAOjC,IAAI,CAACmD;oBACZlB,OAAOjC,IAAI,CAAC;oBACZ,MAAMhE,OAAOmG,SAAS,CAAChG,QAAQmB,KAAK2E,QAAQkB,KAAKzF,MAAM;gBACvD,sEAAsE;gBACvE,EAAE,OAAOgE,OAAO;oBACf4E,WAAW5E,KAAK,CAACA;gBAClB;YACD;YACAqF,OAAMC,MAAM;gBACXnE,OAAOnF,MAAM,GAAG;gBAChB4I,WAAW5E,KAAK,CAACsF;YAClB;QACD;IACD;IAEAC,OAAO9J,IAAwB,EAAEtB,OAAa,EAAsB;QACnE,IAAI,OAAOsB,SAAS,YAAYA,MAAMkB,SAAS,QAAQ;YACtD;QACD;QACA,MAAMf,MAAM,OAAOH,SAAS,WAAW,IAAI,CAACD,YAAY,CAACC,QAAQ,IAAI,CAACD,YAAY,CAACC,KAAKA,IAAI;QAC5F,IAAI,CAACG,KAAK;YACT;QACD;QAEA,2DAA2D;QAC3D,sEAAsE;QACtE,8EAA8E;QAC9E,OAAO0I;IACR;AACD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/fs/minio/index.ts"],"sourcesContent":["export { createMinioFileSystem, type CreateMinioFileSystemOptions } from './createMinioFileSystem';\n"],"names":["createMinioFileSystem"],"mappings":"AAAA,SAASA,qBAAqB,QAA2C,0BAA0B"}
|
|
@@ -18,7 +18,7 @@ let ContractFS = class ContractFS {
|
|
|
18
18
|
mtime: stat.mtime.getTime()
|
|
19
19
|
}));
|
|
20
20
|
}
|
|
21
|
-
async stat(entry,
|
|
21
|
+
async stat(entry, _options) {
|
|
22
22
|
const { data } = await this.client.stat({
|
|
23
23
|
path: entry
|
|
24
24
|
});
|
|
@@ -82,10 +82,10 @@ let ContractFS = class ContractFS {
|
|
|
82
82
|
force: options?.force
|
|
83
83
|
});
|
|
84
84
|
}
|
|
85
|
-
createReadStream(
|
|
85
|
+
createReadStream(_path, _options) {
|
|
86
86
|
throw new Error('createReadStream is not implemented in ContractFS');
|
|
87
87
|
}
|
|
88
|
-
createWriteStream(
|
|
88
|
+
createWriteStream(_path, _options) {
|
|
89
89
|
throw new Error('createWriteStream is not implemented in ContractFS');
|
|
90
90
|
}
|
|
91
91
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/fs/orpc/createContractClientFileSystem.ts"],"sourcesContent":["import type { Readable, Writable } from 'node:stream';\nimport type { ContractRouterClient } from '@orpc/contract';\nimport { ArrayBuffers } from '@wener/utils';\nimport type {\n\tCopyOptions,\n\tCreateReadStreamOptions,\n\tCreateWriteStreamOptions,\n\tIFileSystem,\n\tMkdirOptions,\n\tReaddirOptions,\n\tReadFileOptions,\n\tRenameOptions,\n\tRmOptions,\n\tStatOptions,\n\tWritableData,\n\tWriteFileOptions,\n} from '../IFileSystem';\nimport { resolveData } from '../utils';\nimport { FileSystemContract } from './FileSystemContract';\n\ntype FileSystemContractClient = ContractRouterClient<typeof FileSystemContract>;\n\nexport function createContractClientFileSystem(client: FileSystemContractClient): IFileSystem & {\n\tclient: FileSystemContractClient;\n} {\n\treturn new ContractFS(client);\n}\n\nclass ContractFS implements IFileSystem {\n\tclient: FileSystemContractClient;\n\n\tconstructor(client: FileSystemContractClient) {\n\t\tthis.client = client;\n\t}\n\n\tasync readdir(dir: string, options: ReaddirOptions = {}) {\n\t\tconst { data } = await this.client.readdir({ dir, ...options });\n\t\treturn data.map((stat) => ({\n\t\t\t...stat,\n\t\t\tmtime: stat.mtime.getTime(),\n\t\t}));\n\t}\n\n\tasync stat(entry: string,
|
|
1
|
+
{"version":3,"sources":["../../../src/fs/orpc/createContractClientFileSystem.ts"],"sourcesContent":["import type { Readable, Writable } from 'node:stream';\nimport type { ContractRouterClient } from '@orpc/contract';\nimport { ArrayBuffers } from '@wener/utils';\nimport type {\n\tCopyOptions,\n\tCreateReadStreamOptions,\n\tCreateWriteStreamOptions,\n\tIFileSystem,\n\tMkdirOptions,\n\tReaddirOptions,\n\tReadFileOptions,\n\tRenameOptions,\n\tRmOptions,\n\tStatOptions,\n\tWritableData,\n\tWriteFileOptions,\n} from '../IFileSystem';\nimport { resolveData } from '../utils';\nimport type { FileSystemContract } from './FileSystemContract';\n\ntype FileSystemContractClient = ContractRouterClient<typeof FileSystemContract>;\n\nexport function createContractClientFileSystem(client: FileSystemContractClient): IFileSystem & {\n\tclient: FileSystemContractClient;\n} {\n\treturn new ContractFS(client);\n}\n\nclass ContractFS implements IFileSystem {\n\tclient: FileSystemContractClient;\n\n\tconstructor(client: FileSystemContractClient) {\n\t\tthis.client = client;\n\t}\n\n\tasync readdir(dir: string, options: ReaddirOptions = {}) {\n\t\tconst { data } = await this.client.readdir({ dir, ...options });\n\t\treturn data.map((stat) => ({\n\t\t\t...stat,\n\t\t\tmtime: stat.mtime.getTime(),\n\t\t}));\n\t}\n\n\tasync stat(entry: string, _options?: StatOptions) {\n\t\tconst { data } = await this.client.stat({ path: entry });\n\t\treturn {\n\t\t\t...data,\n\t\t\tmtime: data.mtime.getTime(),\n\t\t};\n\t}\n\n\tasync mkdir(path: string, options?: MkdirOptions) {\n\t\tawait this.client.mkdir({\n\t\t\tpath,\n\t\t\trecursive: options?.recursive,\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\t// Note: The contract doesn't currently support encoding options.\n\t\tconst { base64 } = await this.client.readFile({ path });\n\t\tlet enc = options?.encoding || 'binary';\n\t\tlet buf = ArrayBuffers.fromBase64(base64);\n\t\tswitch (enc) {\n\t\t\tcase 'text':\n\t\t\t\treturn ArrayBuffers.toString(buf);\n\t\t}\n\t\treturn buf;\n\t}\n\n\tasync writeFile(path: string, data: WritableData, options?: WriteFileOptions) {\n\t\tlet buf = resolveData(data);\n\t\tawait this.client.writeFile({ path, base64: ArrayBuffers.toBase64(buf as BufferSource), ...options });\n\t}\n\n\tasync rename(oldPath: string, newPath: string, options?: RenameOptions) {\n\t\tawait this.client.rename({\n\t\t\toldPath,\n\t\t\tnewPath,\n\t\t\toverwrite: options?.overwrite,\n\t\t});\n\t}\n\n\tasync exists(path: string) {\n\t\tconst { data } = await this.client.exists({ path });\n\t\treturn data;\n\t}\n\n\tasync copy(src: string, dest: string, options?: CopyOptions) {\n\t\tawait this.client.copy({\n\t\t\tsrc,\n\t\t\tdest,\n\t\t\toverwrite: options?.overwrite,\n\t\t\tshallow: options?.shallow,\n\t\t});\n\t}\n\n\tasync rm(path: string, options?: RmOptions) {\n\t\tawait this.client.rm({\n\t\t\tpath,\n\t\t\trecursive: options?.recursive,\n\t\t\tforce: options?.force,\n\t\t});\n\t}\n\n\tcreateReadStream(_path: string, _options?: CreateReadStreamOptions): Readable {\n\t\tthrow new Error('createReadStream is not implemented in ContractFS');\n\t}\n\n\tcreateWriteStream(_path: string, _options?: CreateWriteStreamOptions): Writable {\n\t\tthrow new Error('createWriteStream is not implemented in ContractFS');\n\t}\n}\n"],"names":["ArrayBuffers","resolveData","createContractClientFileSystem","client","ContractFS","readdir","dir","options","data","map","stat","mtime","getTime","entry","_options","path","mkdir","recursive","readFile","base64","enc","encoding","buf","fromBase64","toString","writeFile","toBase64","rename","oldPath","newPath","overwrite","exists","copy","src","dest","shallow","rm","force","createReadStream","_path","Error","createWriteStream"],"mappings":"AAEA,SAASA,YAAY,QAAQ,eAAe;AAe5C,SAASC,WAAW,QAAQ,WAAW;AAKvC,OAAO,SAASC,+BAA+BC,MAAgC;IAG9E,OAAO,IAAIC,WAAWD;AACvB;AAEA,IAAA,AAAMC,aAAN,MAAMA;IACLD,OAAiC;IAEjC,YAAYA,MAAgC,CAAE;QAC7C,IAAI,CAACA,MAAM,GAAGA;IACf;IAEA,MAAME,QAAQC,GAAW,EAAEC,UAA0B,CAAC,CAAC,EAAE;QACxD,MAAM,EAAEC,IAAI,EAAE,GAAG,MAAM,IAAI,CAACL,MAAM,CAACE,OAAO,CAAC;YAAEC;YAAK,GAAGC,OAAO;QAAC;QAC7D,OAAOC,KAAKC,GAAG,CAAC,CAACC,OAAU,CAAA;gBAC1B,GAAGA,IAAI;gBACPC,OAAOD,KAAKC,KAAK,CAACC,OAAO;YAC1B,CAAA;IACD;IAEA,MAAMF,KAAKG,KAAa,EAAEC,QAAsB,EAAE;QACjD,MAAM,EAAEN,IAAI,EAAE,GAAG,MAAM,IAAI,CAACL,MAAM,CAACO,IAAI,CAAC;YAAEK,MAAMF;QAAM;QACtD,OAAO;YACN,GAAGL,IAAI;YACPG,OAAOH,KAAKG,KAAK,CAACC,OAAO;QAC1B;IACD;IAEA,MAAMI,MAAMD,IAAY,EAAER,OAAsB,EAAE;QACjD,MAAM,IAAI,CAACJ,MAAM,CAACa,KAAK,CAAC;YACvBD;YACAE,WAAWV,SAASU;QACrB;IACD;IAIA,MAAMC,SAASH,IAAY,EAAER,OAAyB,EAAgC;QACrF,iEAAiE;QACjE,MAAM,EAAEY,MAAM,EAAE,GAAG,MAAM,IAAI,CAAChB,MAAM,CAACe,QAAQ,CAAC;YAAEH;QAAK;QACrD,IAAIK,MAAMb,SAASc,YAAY;QAC/B,IAAIC,MAAMtB,aAAauB,UAAU,CAACJ;QAClC,OAAQC;YACP,KAAK;gBACJ,OAAOpB,aAAawB,QAAQ,CAACF;QAC/B;QACA,OAAOA;IACR;IAEA,MAAMG,UAAUV,IAAY,EAAEP,IAAkB,EAAED,OAA0B,EAAE;QAC7E,IAAIe,MAAMrB,YAAYO;QACtB,MAAM,IAAI,CAACL,MAAM,CAACsB,SAAS,CAAC;YAAEV;YAAMI,QAAQnB,aAAa0B,QAAQ,CAACJ;YAAsB,GAAGf,OAAO;QAAC;IACpG;IAEA,MAAMoB,OAAOC,OAAe,EAAEC,OAAe,EAAEtB,OAAuB,EAAE;QACvE,MAAM,IAAI,CAACJ,MAAM,CAACwB,MAAM,CAAC;YACxBC;YACAC;YACAC,WAAWvB,SAASuB;QACrB;IACD;IAEA,MAAMC,OAAOhB,IAAY,EAAE;QAC1B,MAAM,EAAEP,IAAI,EAAE,GAAG,MAAM,IAAI,CAACL,MAAM,CAAC4B,MAAM,CAAC;YAAEhB;QAAK;QACjD,OAAOP;IACR;IAEA,MAAMwB,KAAKC,GAAW,EAAEC,IAAY,EAAE3B,OAAqB,EAAE;QAC5D,MAAM,IAAI,CAACJ,MAAM,CAAC6B,IAAI,CAAC;YACtBC;YACAC;YACAJ,WAAWvB,SAASuB;YACpBK,SAAS5B,SAAS4B;QACnB;IACD;IAEA,MAAMC,GAAGrB,IAAY,EAAER,OAAmB,EAAE;QAC3C,MAAM,IAAI,CAACJ,MAAM,CAACiC,EAAE,CAAC;YACpBrB;YACAE,WAAWV,SAASU;YACpBoB,OAAO9B,SAAS8B;QACjB;IACD;IAEAC,iBAAiBC,KAAa,EAAEzB,QAAkC,EAAY;QAC7E,MAAM,IAAI0B,MAAM;IACjB;IAEAC,kBAAkBF,KAAa,EAAEzB,QAAmC,EAAY;QAC/E,MAAM,IAAI0B,MAAM;IACjB;AACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/fs/orpc/server/createFileSystemContractImpl.ts"],"sourcesContent":["import { implement } from '@orpc/server';\nimport { ArrayBuffers } from '@wener/utils';\nimport type { IFileSystem } from '../../IFileSystem';\nimport { FileSystemContract } from '../FileSystemContract';\n\nexport function createFileSystemContractImpl(ifs: IFileSystem) {\n\tconst os = implement(FileSystemContract);\n\n\treturn {\n\t\treaddir: os.readdir.handler(async ({ input }) => {\n\t\t\treturn {\n\t\t\t\tdata: await ifs.readdir(input.dir),\n\t\t\t};\n\t\t}),\n\t\tstat: os.stat.handler(async ({ input }) => {\n\t\t\treturn {\n\t\t\t\tdata: await ifs.stat(input.path),\n\t\t\t};\n\t\t}),\n\t\tmkdir: os.mkdir.handler(async ({ input }) => {\n\t\t\tawait ifs.mkdir(input.path, {\n\t\t\t\trecursive: input.recursive ?? false,\n\t\t\t});\n\t\t\treturn {};\n\t\t}),\n\t\trename: os.rename.handler(async ({ input }) => {\n\t\t\tawait ifs.rename(input.oldPath, input.newPath, {\n\t\t\t\toverwrite: input.overwrite ?? false,\n\t\t\t});\n\t\t\treturn {};\n\t\t}),\n\t\texists: os.exists.handler(async ({ input }) => {\n\t\t\treturn {\n\t\t\t\tdata: await ifs.exists(input.path),\n\t\t\t};\n\t\t}),\n\t\tcopy: os.copy.handler(async ({ input }) => {\n\t\t\tawait ifs.copy(input.src, input.dest, {\n\t\t\t\toverwrite: input.overwrite ?? false,\n\t\t\t\tshallow: input.shallow ?? false,\n\t\t\t});\n\t\t\treturn {};\n\t\t}),\n\t\treadFile: os.readFile.handler(async ({ input }) => {\n\t\t\treturn {\n\t\t\t\tbase64: ArrayBuffers.toBase64(await ifs.readFile(input.path, { encoding: 'binary' })),\n\t\t\t};\n\t\t}),\n\t\twriteFile: os.writeFile.handler(async ({ input }) => {\n\t\t\tawait ifs.writeFile(input.path, Buffer.from(input.base64, 'base64'), {\n\t\t\t\toverwrite: input.overwrite,\n\t\t\t});\n\t\t\treturn {};\n\t\t}),\n\n\t\trm: os.rm.handler(async ({ input }) => {\n\t\t\tawait ifs.rm(input.path, {\n\t\t\t\trecursive: input.recursive ?? undefined,\n\t\t\t\tforce: input.force ?? undefined,\n\t\t\t});\n\t\t\treturn {};\n\t\t}),\n\t};\n}\n"],"names":["implement","ArrayBuffers","FileSystemContract","createFileSystemContractImpl","ifs","os","readdir","handler","input","data","dir","stat","path","mkdir","recursive","rename","oldPath","newPath","overwrite","exists","copy","src","dest","shallow","readFile","base64","toBase64","encoding","writeFile","Buffer","from","rm","undefined","force"],"mappings":"AAAA,SAASA,SAAS,QAAQ,eAAe;AACzC,SAASC,YAAY,QAAQ,eAAe;AAE5C,SAASC,kBAAkB,QAAQ,wBAAwB;AAE3D,OAAO,SAASC,6BAA6BC,GAAgB;IAC5D,MAAMC,KAAKL,UAAUE;IAErB,OAAO;QACNI,SAASD,GAAGC,OAAO,CAACC,OAAO,CAAC,OAAO,EAAEC,KAAK,EAAE;YAC3C,OAAO;gBACNC,MAAM,MAAML,IAAIE,OAAO,CAACE,MAAME,GAAG;YAClC;QACD;QACAC,MAAMN,GAAGM,IAAI,CAACJ,OAAO,CAAC,OAAO,EAAEC,KAAK,EAAE;YACrC,OAAO;gBACNC,MAAM,MAAML,IAAIO,IAAI,CAACH,MAAMI,IAAI;YAChC;QACD;QACAC,OAAOR,GAAGQ,KAAK,CAACN,OAAO,CAAC,OAAO,EAAEC,KAAK,EAAE;YACvC,MAAMJ,IAAIS,KAAK,CAACL,MAAMI,IAAI,EAAE;gBAC3BE,WAAWN,MAAMM,SAAS,IAAI;YAC/B;YACA,OAAO,CAAC;QACT;QACAC,QAAQV,GAAGU,MAAM,CAACR,OAAO,CAAC,OAAO,EAAEC,KAAK,EAAE;YACzC,MAAMJ,IAAIW,MAAM,CAACP,MAAMQ,OAAO,EAAER,MAAMS,OAAO,EAAE;gBAC9CC,WAAWV,MAAMU,SAAS,IAAI;YAC/B;YACA,OAAO,CAAC;QACT;QACAC,QAAQd,GAAGc,MAAM,CAACZ,OAAO,CAAC,OAAO,EAAEC,KAAK,EAAE;YACzC,OAAO;gBACNC,MAAM,MAAML,IAAIe,MAAM,CAACX,MAAMI,IAAI;YAClC;QACD;QACAQ,MAAMf,GAAGe,IAAI,CAACb,OAAO,CAAC,OAAO,EAAEC,KAAK,EAAE;YACrC,MAAMJ,IAAIgB,IAAI,CAACZ,MAAMa,GAAG,EAAEb,MAAMc,IAAI,EAAE;gBACrCJ,WAAWV,MAAMU,SAAS,IAAI;gBAC9BK,SAASf,MAAMe,OAAO,IAAI;YAC3B;YACA,OAAO,CAAC;QACT;QACAC,UAAUnB,GAAGmB,QAAQ,CAACjB,OAAO,CAAC,OAAO,EAAEC,KAAK,EAAE;YAC7C,OAAO;gBACNiB,QAAQxB,aAAayB,QAAQ,
|
|
1
|
+
{"version":3,"sources":["../../../../src/fs/orpc/server/createFileSystemContractImpl.ts"],"sourcesContent":["import { implement } from '@orpc/server';\nimport { ArrayBuffers } from '@wener/utils';\nimport type { IFileSystem } from '../../IFileSystem';\nimport { FileSystemContract } from '../FileSystemContract';\n\nexport function createFileSystemContractImpl(ifs: IFileSystem) {\n\tconst os = implement(FileSystemContract);\n\n\treturn {\n\t\treaddir: os.readdir.handler(async ({ input }) => {\n\t\t\treturn {\n\t\t\t\tdata: await ifs.readdir(input.dir),\n\t\t\t};\n\t\t}),\n\t\tstat: os.stat.handler(async ({ input }) => {\n\t\t\treturn {\n\t\t\t\tdata: await ifs.stat(input.path),\n\t\t\t};\n\t\t}),\n\t\tmkdir: os.mkdir.handler(async ({ input }) => {\n\t\t\tawait ifs.mkdir(input.path, {\n\t\t\t\trecursive: input.recursive ?? false,\n\t\t\t});\n\t\t\treturn {};\n\t\t}),\n\t\trename: os.rename.handler(async ({ input }) => {\n\t\t\tawait ifs.rename(input.oldPath, input.newPath, {\n\t\t\t\toverwrite: input.overwrite ?? false,\n\t\t\t});\n\t\t\treturn {};\n\t\t}),\n\t\texists: os.exists.handler(async ({ input }) => {\n\t\t\treturn {\n\t\t\t\tdata: await ifs.exists(input.path),\n\t\t\t};\n\t\t}),\n\t\tcopy: os.copy.handler(async ({ input }) => {\n\t\t\tawait ifs.copy(input.src, input.dest, {\n\t\t\t\toverwrite: input.overwrite ?? false,\n\t\t\t\tshallow: input.shallow ?? false,\n\t\t\t});\n\t\t\treturn {};\n\t\t}),\n\t\treadFile: os.readFile.handler(async ({ input }) => {\n\t\t\treturn {\n\t\t\t\tbase64: ArrayBuffers.toBase64((await ifs.readFile(input.path, { encoding: 'binary' })) as BufferSource),\n\t\t\t};\n\t\t}),\n\t\twriteFile: os.writeFile.handler(async ({ input }) => {\n\t\t\tawait ifs.writeFile(input.path, Buffer.from(input.base64, 'base64'), {\n\t\t\t\toverwrite: input.overwrite,\n\t\t\t});\n\t\t\treturn {};\n\t\t}),\n\n\t\trm: os.rm.handler(async ({ input }) => {\n\t\t\tawait ifs.rm(input.path, {\n\t\t\t\trecursive: input.recursive ?? undefined,\n\t\t\t\tforce: input.force ?? undefined,\n\t\t\t});\n\t\t\treturn {};\n\t\t}),\n\t};\n}\n"],"names":["implement","ArrayBuffers","FileSystemContract","createFileSystemContractImpl","ifs","os","readdir","handler","input","data","dir","stat","path","mkdir","recursive","rename","oldPath","newPath","overwrite","exists","copy","src","dest","shallow","readFile","base64","toBase64","encoding","writeFile","Buffer","from","rm","undefined","force"],"mappings":"AAAA,SAASA,SAAS,QAAQ,eAAe;AACzC,SAASC,YAAY,QAAQ,eAAe;AAE5C,SAASC,kBAAkB,QAAQ,wBAAwB;AAE3D,OAAO,SAASC,6BAA6BC,GAAgB;IAC5D,MAAMC,KAAKL,UAAUE;IAErB,OAAO;QACNI,SAASD,GAAGC,OAAO,CAACC,OAAO,CAAC,OAAO,EAAEC,KAAK,EAAE;YAC3C,OAAO;gBACNC,MAAM,MAAML,IAAIE,OAAO,CAACE,MAAME,GAAG;YAClC;QACD;QACAC,MAAMN,GAAGM,IAAI,CAACJ,OAAO,CAAC,OAAO,EAAEC,KAAK,EAAE;YACrC,OAAO;gBACNC,MAAM,MAAML,IAAIO,IAAI,CAACH,MAAMI,IAAI;YAChC;QACD;QACAC,OAAOR,GAAGQ,KAAK,CAACN,OAAO,CAAC,OAAO,EAAEC,KAAK,EAAE;YACvC,MAAMJ,IAAIS,KAAK,CAACL,MAAMI,IAAI,EAAE;gBAC3BE,WAAWN,MAAMM,SAAS,IAAI;YAC/B;YACA,OAAO,CAAC;QACT;QACAC,QAAQV,GAAGU,MAAM,CAACR,OAAO,CAAC,OAAO,EAAEC,KAAK,EAAE;YACzC,MAAMJ,IAAIW,MAAM,CAACP,MAAMQ,OAAO,EAAER,MAAMS,OAAO,EAAE;gBAC9CC,WAAWV,MAAMU,SAAS,IAAI;YAC/B;YACA,OAAO,CAAC;QACT;QACAC,QAAQd,GAAGc,MAAM,CAACZ,OAAO,CAAC,OAAO,EAAEC,KAAK,EAAE;YACzC,OAAO;gBACNC,MAAM,MAAML,IAAIe,MAAM,CAACX,MAAMI,IAAI;YAClC;QACD;QACAQ,MAAMf,GAAGe,IAAI,CAACb,OAAO,CAAC,OAAO,EAAEC,KAAK,EAAE;YACrC,MAAMJ,IAAIgB,IAAI,CAACZ,MAAMa,GAAG,EAAEb,MAAMc,IAAI,EAAE;gBACrCJ,WAAWV,MAAMU,SAAS,IAAI;gBAC9BK,SAASf,MAAMe,OAAO,IAAI;YAC3B;YACA,OAAO,CAAC;QACT;QACAC,UAAUnB,GAAGmB,QAAQ,CAACjB,OAAO,CAAC,OAAO,EAAEC,KAAK,EAAE;YAC7C,OAAO;gBACNiB,QAAQxB,aAAayB,QAAQ,CAAE,MAAMtB,IAAIoB,QAAQ,CAAChB,MAAMI,IAAI,EAAE;oBAAEe,UAAU;gBAAS;YACpF;QACD;QACAC,WAAWvB,GAAGuB,SAAS,CAACrB,OAAO,CAAC,OAAO,EAAEC,KAAK,EAAE;YAC/C,MAAMJ,IAAIwB,SAAS,CAACpB,MAAMI,IAAI,EAAEiB,OAAOC,IAAI,CAACtB,MAAMiB,MAAM,EAAE,WAAW;gBACpEP,WAAWV,MAAMU,SAAS;YAC3B;YACA,OAAO,CAAC;QACT;QAEAa,IAAI1B,GAAG0B,EAAE,CAACxB,OAAO,CAAC,OAAO,EAAEC,KAAK,EAAE;YACjC,MAAMJ,IAAI2B,EAAE,CAACvB,MAAMI,IAAI,EAAE;gBACxBE,WAAWN,MAAMM,SAAS,IAAIkB;gBAC9BC,OAAOzB,MAAMyB,KAAK,IAAID;YACvB;YACA,OAAO,CAAC;QACT;IACD;AACD"}
|
|
@@ -36,11 +36,11 @@ export function createS3MiniFileSystem(options = {}) {
|
|
|
36
36
|
}
|
|
37
37
|
let S3FS = class S3FS {
|
|
38
38
|
client;
|
|
39
|
-
|
|
39
|
+
_bucket;
|
|
40
40
|
prefix;
|
|
41
|
-
constructor(client,
|
|
41
|
+
constructor(client, _bucket, prefix = ''){
|
|
42
42
|
this.client = client;
|
|
43
|
-
this.
|
|
43
|
+
this._bucket = _bucket;
|
|
44
44
|
this.prefix = prefix;
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
@@ -53,16 +53,16 @@ let S3FS = class S3FS {
|
|
|
53
53
|
const normalized = normalize(path).replace(/^\/+/, '').replace(/\\/g, '/');
|
|
54
54
|
// Prepend prefix if set
|
|
55
55
|
if (this.prefix) {
|
|
56
|
-
return this.prefix
|
|
56
|
+
return `${this.prefix}/${normalized}`;
|
|
57
57
|
}
|
|
58
58
|
return normalized;
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
61
|
* Remove prefix from S3 key to get the file system path
|
|
62
62
|
*/ stripPrefix(key) {
|
|
63
|
-
if (!this.prefix || !key.startsWith(this.prefix
|
|
63
|
+
if (!this.prefix || !key.startsWith(`${this.prefix}/`)) {
|
|
64
64
|
// If key doesn't start with prefix, return as-is (shouldn't happen normally)
|
|
65
|
-
return key.startsWith('/') ? key :
|
|
65
|
+
return key.startsWith('/') ? key : `/${key}`;
|
|
66
66
|
}
|
|
67
67
|
const withoutPrefix = key.slice(this.prefix.length);
|
|
68
68
|
return withoutPrefix || '/';
|
|
@@ -82,7 +82,7 @@ let S3FS = class S3FS {
|
|
|
82
82
|
return '/';
|
|
83
83
|
}
|
|
84
84
|
const dir = dirname(key).replace(/\\/g, '/');
|
|
85
|
-
return dir === '.' ? '/' :
|
|
85
|
+
return dir === '.' ? '/' : `/${dir}`;
|
|
86
86
|
}
|
|
87
87
|
/**
|
|
88
88
|
* Check if a key represents a directory (ends with /)
|
|
@@ -116,67 +116,99 @@ let S3FS = class S3FS {
|
|
|
116
116
|
const { glob, recursive, depth = 1, kind, hidden = true, signal } = options;
|
|
117
117
|
this.checkAborted(signal);
|
|
118
118
|
const dirPrefix = this.normalizeKey(dir);
|
|
119
|
-
const prefixWithSlash = dirPrefix ? dirPrefix.endsWith('/') ? dirPrefix : dirPrefix
|
|
119
|
+
const prefixWithSlash = dirPrefix ? dirPrefix.endsWith('/') ? dirPrefix : `${dirPrefix}/` : '';
|
|
120
120
|
try {
|
|
121
|
-
|
|
122
|
-
//
|
|
123
|
-
// -
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
121
|
+
const delimiter = recursive ? '' : '/';
|
|
122
|
+
// S3mini doesn't expose CommonPrefixes from delimiter-based listing.
|
|
123
|
+
// For non-recursive listing, we do two calls:
|
|
124
|
+
// 1. With delimiter to get direct files
|
|
125
|
+
// 2. Without delimiter to infer directory prefixes
|
|
126
|
+
let objects = [];
|
|
127
|
+
let commonPrefixes = [];
|
|
128
|
+
if (delimiter && !recursive) {
|
|
129
|
+
const directObjects = await this.client.listObjects(delimiter, prefixWithSlash, undefined, {
|
|
130
|
+
delimiter,
|
|
131
|
+
signal
|
|
132
|
+
});
|
|
133
|
+
if (directObjects) {
|
|
134
|
+
objects = directObjects;
|
|
135
|
+
}
|
|
136
|
+
// Infer CommonPrefixes by listing all objects recursively
|
|
137
|
+
const allObjectsRecursive = await this.client.listObjects('', prefixWithSlash, 1000, {
|
|
138
|
+
signal
|
|
139
|
+
});
|
|
140
|
+
if (allObjectsRecursive) {
|
|
141
|
+
const prefixSet = new Set();
|
|
142
|
+
for (const obj of allObjectsRecursive){
|
|
143
|
+
const key = obj.Key || '';
|
|
144
|
+
if (!key || !key.startsWith(prefixWithSlash)) continue;
|
|
145
|
+
const relativeKey = key.slice(prefixWithSlash.length);
|
|
146
|
+
const firstSlash = relativeKey.indexOf('/');
|
|
147
|
+
if (firstSlash > 0) {
|
|
148
|
+
prefixSet.add(prefixWithSlash + relativeKey.slice(0, firstSlash + 1));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
commonPrefixes = Array.from(prefixSet).sort();
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
const listResult = await this.client.listObjects(delimiter, prefixWithSlash, undefined, {
|
|
155
|
+
signal
|
|
156
|
+
});
|
|
157
|
+
if (listResult) {
|
|
158
|
+
objects = listResult;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (!objects.length && !commonPrefixes.length) {
|
|
130
162
|
return [];
|
|
131
163
|
}
|
|
132
164
|
let results = [];
|
|
133
|
-
|
|
165
|
+
// Process inferred CommonPrefixes (directories)
|
|
166
|
+
for (const prefix of commonPrefixes){
|
|
167
|
+
this.checkAborted(signal);
|
|
168
|
+
if (prefixWithSlash && !prefix.startsWith(prefixWithSlash)) continue;
|
|
169
|
+
const relativePrefix = prefixWithSlash ? prefix.slice(prefixWithSlash.length) : prefix;
|
|
170
|
+
const dirName = relativePrefix.replace(/\/$/, '');
|
|
171
|
+
if (!dirName) continue;
|
|
172
|
+
if (!recursive && depth === 1) {
|
|
173
|
+
if (dirName.indexOf('/') >= 0) continue;
|
|
174
|
+
}
|
|
175
|
+
const dirKey = prefix.endsWith('/') ? prefix : `${prefix}/`;
|
|
176
|
+
const stat = this.toFileStat(dirKey, {
|
|
177
|
+
Key: dirKey,
|
|
178
|
+
Size: 0,
|
|
179
|
+
LastModified: new Date()
|
|
180
|
+
});
|
|
181
|
+
if (!hidden && stat.name.startsWith('.')) continue;
|
|
182
|
+
if (kind && stat.kind !== kind) continue;
|
|
183
|
+
results.push(stat);
|
|
184
|
+
}
|
|
185
|
+
// Process objects (files and explicit directory markers)
|
|
186
|
+
const seenDirs = new Set();
|
|
134
187
|
for (const obj of objects){
|
|
135
188
|
this.checkAborted(signal);
|
|
136
189
|
const key = obj.Key || '';
|
|
137
190
|
if (!key) continue;
|
|
138
|
-
|
|
139
|
-
if (prefixWithSlash && !key.startsWith(prefixWithSlash)) {
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
142
|
-
// Strip the prefix from the key for relative path calculation
|
|
191
|
+
if (prefixWithSlash && !key.startsWith(prefixWithSlash)) continue;
|
|
143
192
|
const relativeKey = prefixWithSlash ? key.slice(prefixWithSlash.length) : key;
|
|
144
|
-
|
|
145
|
-
if (!relativeKey || relativeKey === '/') {
|
|
146
|
-
continue;
|
|
147
|
-
}
|
|
148
|
-
// Directory: Key ends with '/' (from CommonPrefixes or explicit marker)
|
|
149
|
-
const isDir = key.endsWith('/');
|
|
150
|
-
// For non-recursive, only show immediate children
|
|
193
|
+
if (!relativeKey || relativeKey === '/') continue;
|
|
151
194
|
if (!recursive && depth === 1) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
// We only want immediate children, so no more slashes in the middle
|
|
155
|
-
const keyWithoutTrailingSlash = relativeKey.replace(/\/$/, '');
|
|
156
|
-
if (keyWithoutTrailingSlash.includes('/')) {
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
195
|
+
const firstSlash = relativeKey.indexOf('/');
|
|
196
|
+
if (firstSlash >= 0) continue;
|
|
159
197
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
continue;
|
|
198
|
+
const isDir = this.isDirectoryKey(key);
|
|
199
|
+
if (isDir) {
|
|
200
|
+
const dk = key.slice(0, -1);
|
|
201
|
+
if (seenDirs.has(dk)) continue;
|
|
202
|
+
seenDirs.add(dk);
|
|
164
203
|
}
|
|
165
|
-
seenPaths.add(pathKey);
|
|
166
204
|
const stat = this.toFileStat(key, {
|
|
167
205
|
Key: key,
|
|
168
206
|
Size: obj.Size,
|
|
169
207
|
LastModified: obj.LastModified,
|
|
170
208
|
ETag: obj.ETag
|
|
171
209
|
});
|
|
172
|
-
|
|
173
|
-
if (
|
|
174
|
-
continue;
|
|
175
|
-
}
|
|
176
|
-
// Filter by kind
|
|
177
|
-
if (kind && stat.kind !== kind) {
|
|
178
|
-
continue;
|
|
179
|
-
}
|
|
210
|
+
if (!hidden && stat.name.startsWith('.')) continue;
|
|
211
|
+
if (kind && stat.kind !== kind) continue;
|
|
180
212
|
results.push(stat);
|
|
181
213
|
}
|
|
182
214
|
// Handle recursive with depth > 1
|
|
@@ -252,7 +284,7 @@ let S3FS = class S3FS {
|
|
|
252
284
|
});
|
|
253
285
|
}
|
|
254
286
|
// If object not found, try checking if it's a directory (prefix listing)
|
|
255
|
-
const dirKey = key.endsWith('/') ? key : key
|
|
287
|
+
const dirKey = key.endsWith('/') ? key : `${key}/`;
|
|
256
288
|
const objects = await this.client.listObjects('/', dirKey, 1, {
|
|
257
289
|
delimiter: '/',
|
|
258
290
|
signal
|
|
@@ -278,7 +310,7 @@ let S3FS = class S3FS {
|
|
|
278
310
|
}
|
|
279
311
|
}
|
|
280
312
|
async mkdir(path, options = {}) {
|
|
281
|
-
const { recursive = false, signal } = options;
|
|
313
|
+
const { recursive: _recursive = false, signal } = options;
|
|
282
314
|
this.checkAborted(signal);
|
|
283
315
|
// In S3, directories don't actually exist - they're just prefixes
|
|
284
316
|
// Optionally create a marker object (empty object with trailing slash)
|
|
@@ -287,7 +319,7 @@ let S3FS = class S3FS {
|
|
|
287
319
|
return; // Root directory, nothing to do
|
|
288
320
|
}
|
|
289
321
|
// Ensure it ends with / to indicate directory
|
|
290
|
-
const dirKey = key.endsWith('/') ? key : key
|
|
322
|
+
const dirKey = key.endsWith('/') ? key : `${key}/`;
|
|
291
323
|
// Try to create a marker object (0-byte object)
|
|
292
324
|
try {
|
|
293
325
|
await this.client.putObject(dirKey, '', 'application/x-directory', undefined, undefined);
|
|
@@ -347,7 +379,27 @@ let S3FS = class S3FS {
|
|
|
347
379
|
}
|
|
348
380
|
// Convert data to buffer or string
|
|
349
381
|
let body;
|
|
350
|
-
if (data instanceof
|
|
382
|
+
if (data instanceof ReadableStream) {
|
|
383
|
+
// Handle web ReadableStream
|
|
384
|
+
const reader = data.getReader();
|
|
385
|
+
const chunks = [];
|
|
386
|
+
let loaded = 0;
|
|
387
|
+
while(true){
|
|
388
|
+
const { done, value } = await reader.read();
|
|
389
|
+
if (done) break;
|
|
390
|
+
if (value) {
|
|
391
|
+
chunks.push(value);
|
|
392
|
+
loaded += value.length;
|
|
393
|
+
if (onUploadProgress) {
|
|
394
|
+
onUploadProgress({
|
|
395
|
+
loaded,
|
|
396
|
+
total: -1
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
body = Buffer.concat(chunks);
|
|
402
|
+
} else if (data instanceof Readable) {
|
|
351
403
|
// For streams, we need to read them into a buffer
|
|
352
404
|
const chunks = [];
|
|
353
405
|
let loaded = 0;
|
|
@@ -387,11 +439,7 @@ let S3FS = class S3FS {
|
|
|
387
439
|
// ArrayBufferView
|
|
388
440
|
body = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
|
389
441
|
}
|
|
390
|
-
|
|
391
|
-
await this.client.putObject(key, body, undefined, undefined, undefined);
|
|
392
|
-
} catch (error) {
|
|
393
|
-
throw error;
|
|
394
|
-
}
|
|
442
|
+
await this.client.putObject(key, body, undefined, undefined, undefined);
|
|
395
443
|
}
|
|
396
444
|
async rm(path, options = {}) {
|
|
397
445
|
const { recursive = false, force = false, signal } = options;
|
|
@@ -403,7 +451,7 @@ let S3FS = class S3FS {
|
|
|
403
451
|
try {
|
|
404
452
|
if (recursive) {
|
|
405
453
|
// List all objects with this prefix (no delimiter = recursive)
|
|
406
|
-
const prefix = key.endsWith('/') ? key : key
|
|
454
|
+
const prefix = key.endsWith('/') ? key : `${key}/`;
|
|
407
455
|
const objects = await this.client.listObjects('', prefix, undefined, {
|
|
408
456
|
signal
|
|
409
457
|
});
|
|
@@ -450,13 +498,13 @@ let S3FS = class S3FS {
|
|
|
450
498
|
try {
|
|
451
499
|
// Check if it's a directory (has objects with prefix)
|
|
452
500
|
const isDir = oldKey.endsWith('/');
|
|
453
|
-
const prefix = isDir ? oldKey : oldKey
|
|
501
|
+
const prefix = isDir ? oldKey : `${oldKey}/`;
|
|
454
502
|
const objects = await this.client.listObjects('', prefix, undefined, {
|
|
455
503
|
signal
|
|
456
504
|
});
|
|
457
505
|
if (objects && objects.length > 0) {
|
|
458
506
|
// It's a directory or has multiple objects, move all
|
|
459
|
-
const newPrefix = newKey.endsWith('/') ? newKey : newKey
|
|
507
|
+
const newPrefix = newKey.endsWith('/') ? newKey : `${newKey}/`;
|
|
460
508
|
// Move all objects
|
|
461
509
|
await Promise.all(objects.map(async (obj)=>{
|
|
462
510
|
const objKey = obj.Key || '';
|
|
@@ -494,7 +542,7 @@ let S3FS = class S3FS {
|
|
|
494
542
|
return true;
|
|
495
543
|
}
|
|
496
544
|
// Check if it's a directory
|
|
497
|
-
const dirKey = key.endsWith('/') ? key : key
|
|
545
|
+
const dirKey = key.endsWith('/') ? key : `${key}/`;
|
|
498
546
|
const objects = await this.client.listObjects('/', dirKey, 1, {
|
|
499
547
|
delimiter: '/'
|
|
500
548
|
});
|
|
@@ -523,8 +571,8 @@ let S3FS = class S3FS {
|
|
|
523
571
|
}
|
|
524
572
|
if (srcStat.kind === 'directory') {
|
|
525
573
|
// Copy directory recursively
|
|
526
|
-
const srcPrefix = srcKey.endsWith('/') ? srcKey : srcKey
|
|
527
|
-
const destPrefix = destKey.endsWith('/') ? destKey : destKey
|
|
574
|
+
const srcPrefix = srcKey.endsWith('/') ? srcKey : `${srcKey}/`;
|
|
575
|
+
const destPrefix = destKey.endsWith('/') ? destKey : `${destKey}/`;
|
|
528
576
|
const objects = await this.client.listObjects(shallow ? '/' : '', srcPrefix, undefined, {
|
|
529
577
|
...shallow ? {
|
|
530
578
|
delimiter: '/'
|
|
@@ -581,7 +629,7 @@ let S3FS = class S3FS {
|
|
|
581
629
|
}
|
|
582
630
|
// Convert ReadableStream to Node Readable
|
|
583
631
|
const reader = response.body.getReader();
|
|
584
|
-
const
|
|
632
|
+
const _decoder = new TextDecoder();
|
|
585
633
|
nodeStream = new Readable({
|
|
586
634
|
async read () {
|
|
587
635
|
try {
|
|
@@ -658,7 +706,7 @@ let S3FS = class S3FS {
|
|
|
658
706
|
if (!key) {
|
|
659
707
|
throw new Error('Cannot write to root directory');
|
|
660
708
|
}
|
|
661
|
-
const { signal, overwrite = true } = options;
|
|
709
|
+
const { signal, overwrite: _overwrite = true } = options;
|
|
662
710
|
this.checkAborted(signal);
|
|
663
711
|
// Create a WritableStream that buffers data and uploads when done
|
|
664
712
|
const buffer = [];
|
|
@@ -688,7 +736,7 @@ let S3FS = class S3FS {
|
|
|
688
736
|
}
|
|
689
737
|
});
|
|
690
738
|
}
|
|
691
|
-
getUrl(path,
|
|
739
|
+
getUrl(path, _options) {
|
|
692
740
|
if (typeof path === 'object' && path?.kind !== 'file') {
|
|
693
741
|
return;
|
|
694
742
|
}
|