From 2cf41f3d77a2cf0c78675811c700663dfd96c36d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E4=B8=80=E4=B9=8B?= Date: Tue, 3 Feb 2026 12:06:33 +0800 Subject: [PATCH 01/15] =?UTF-8?q?=E5=A2=9E=E5=8A=A0s3=E5=AD=98=E5=82=A8=20?= =?UTF-8?q?#1146?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + packages/filesystem/factory.ts | 19 +- packages/filesystem/s3/rw.ts | 116 ++ packages/filesystem/s3/s3.ts | 227 +++ pnpm-lock.yaml | 1250 +++++++++++++++++ src/locales/ach-UG/translation.json | 5 + src/locales/de-DE/translation.json | 5 + src/locales/en-US/translation.json | 5 + src/locales/ja-JP/translation.json | 5 + src/locales/ru-RU/translation.json | 5 + src/locales/vi-VN/translation.json | 5 + src/locales/zh-CN/translation.json | 5 + src/locales/zh-TW/translation.json | 5 + .../components/FileSystemParams/index.tsx | 4 + 14 files changed, 1656 insertions(+), 1 deletion(-) create mode 100644 packages/filesystem/s3/rw.ts create mode 100644 packages/filesystem/s3/s3.ts diff --git a/package.json b/package.json index 7d851ce21..251dd01aa 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ }, "dependencies": { "@arco-design/web-react": "^2.66.7", + "@aws-sdk/client-s3": "^3.981.0", "@dnd-kit/core": "^6.3.1", "@dnd-kit/modifiers": "^9.0.0", "@dnd-kit/sortable": "^10.0.0", diff --git a/packages/filesystem/factory.ts b/packages/filesystem/factory.ts index 24aca3e4c..bdeb26e16 100644 --- a/packages/filesystem/factory.ts +++ b/packages/filesystem/factory.ts @@ -5,10 +5,11 @@ import OneDriveFileSystem from "./onedrive/onedrive"; import DropboxFileSystem from "./dropbox/dropbox"; import WebDAVFileSystem from "./webdav/webdav"; import ZipFileSystem from "./zip/zip"; +import S3FileSystem from "./s3/s3"; import { t } from "@App/locales/locales"; import LimiterFileSystem from "./limiter"; -export type FileSystemType = "zip" | "webdav" | "baidu-netdsik" | "onedrive" | "googledrive" | "dropbox"; +export type FileSystemType = "zip" | "webdav" | "baidu-netdsik" | "onedrive" | "googledrive" | "dropbox" | "s3"; export type FileSystemParams = { [key: string]: { @@ -40,6 +41,15 @@ export default class FileSystemFactory { case "dropbox": fs = new DropboxFileSystem(); break; + case "s3": + fs = new S3FileSystem( + params.bucket, + params.region, + params.accessKeyId, + params.secretAccessKey, + params.endpoint + ); + break; default: throw new Error("not found filesystem"); } @@ -63,6 +73,13 @@ export default class FileSystemFactory { onedrive: {}, googledrive: {}, dropbox: {}, + s3: { + bucket: { title: t("s3_bucket_name") }, + region: { title: t("s3_region") }, + accessKeyId: { title: t("s3_access_key_id") }, + secretAccessKey: { title: t("s3_secret_access_key"), type: "password" }, + endpoint: { title: t("s3_custom_endpoint") }, + }, }; } diff --git a/packages/filesystem/s3/rw.ts b/packages/filesystem/s3/rw.ts new file mode 100644 index 000000000..b7e8fe198 --- /dev/null +++ b/packages/filesystem/s3/rw.ts @@ -0,0 +1,116 @@ +import { GetObjectCommand, PutObjectCommand } from "@aws-sdk/client-s3"; +import type { S3Client } from "@aws-sdk/client-s3"; +import type { FileReader, FileWriter } from "../filesystem"; + +/** + * FileReader implementation for Amazon S3. + * Downloads and reads file content from S3. + */ +export class S3FileReader implements FileReader { + client: S3Client; + + bucket: string; + + key: string; + + constructor(client: S3Client, bucket: string, key: string) { + this.client = client; + this.bucket = bucket; + this.key = key; + } + + /** + * Reads file content from S3. + * @param type - Output format: "string" for text, "blob" for binary (default) + * @returns File content as string or Blob + * @throws {Error} If file not found or read fails + */ + async read(type?: "string" | "blob"): Promise { + try { + const command = new GetObjectCommand({ + Bucket: this.bucket, + Key: this.key, + }); + + const response = await this.client.send(command); + + if (!response.Body) { + throw new Error("Empty response body from S3"); + } + + // Convert the stream to the requested format + const chunks: Uint8Array[] = []; + const reader = response.Body.transformToWebStream().getReader(); + + while (true) { + const { done, value } = await reader.read(); + if (done) break; + chunks.push(value); + } + + const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0); + const result = new Uint8Array(totalLength); + let offset = 0; + for (const chunk of chunks) { + result.set(chunk, offset); + offset += chunk.length; + } + + switch (type) { + case "string": + return new TextDecoder().decode(result); + default: + return new Blob([result]); + } + } catch (error: any) { + if (error.name === "NoSuchKey") { + throw new Error(`File not found: ${this.key}`); + } + throw error; + } + } +} + +/** + * FileWriter implementation for Amazon S3. + * Uploads file content to S3 with optional metadata. + */ +export class S3FileWriter implements FileWriter { + client: S3Client; + + bucket: string; + + key: string; + + modifiedDate?: number; + + constructor(client: S3Client, bucket: string, key: string, modifiedDate?: number) { + this.client = client; + this.bucket = bucket; + this.key = key; + this.modifiedDate = modifiedDate; + } + + /** + * Writes content to S3. + * @param content - File content as string or Blob + * @throws {Error} If upload fails + */ + async write(content: string | Blob): Promise { + const body = content instanceof Blob ? new Uint8Array(await content.arrayBuffer()) : content; + + const metadata: Record = {}; + if (this.modifiedDate) { + metadata.createtime = this.modifiedDate.toString(); + } + + const command = new PutObjectCommand({ + Bucket: this.bucket, + Key: this.key, + Body: body, + Metadata: Object.keys(metadata).length > 0 ? metadata : undefined, + }); + + await this.client.send(command); + } +} diff --git a/packages/filesystem/s3/s3.ts b/packages/filesystem/s3/s3.ts new file mode 100644 index 000000000..8f5310135 --- /dev/null +++ b/packages/filesystem/s3/s3.ts @@ -0,0 +1,227 @@ +import { + S3Client, + HeadBucketCommand, + ListObjectsV2Command, + DeleteObjectCommand, + type S3ClientConfig, +} from "@aws-sdk/client-s3"; +import type FileSystem from "../filesystem"; +import type { FileInfo, FileCreateOptions, FileReader, FileWriter } from "../filesystem"; +import { joinPath } from "../utils"; +import { S3FileReader, S3FileWriter } from "./rw"; +import { WarpTokenError } from "../error"; + +/** + * Amazon S3 implementation of the FileSystem interface. + * Supports AWS S3 and S3-compatible services (MinIO, Wasabi, etc.). + */ +export default class S3FileSystem implements FileSystem { + client: S3Client; + + bucket: string; + + region: string; + + basePath: string = "/"; + + /** + * Creates a new S3FileSystem instance. + * + * @param bucket - S3 bucket name + * @param region - AWS region (e.g., "us-east-1") + * @param accessKeyId - AWS access key ID + * @param secretAccessKey - AWS secret access key + * @param endpoint - Optional custom endpoint for S3-compatible services + * @param basePath - Optional base path for directory scoping + */ + constructor( + bucket: string, + region: string, + accessKeyId: string, + secretAccessKey: string, + endpoint?: string, + basePath?: string + ) { + this.bucket = bucket; + this.region = region; + this.basePath = basePath || "/"; + + const config: S3ClientConfig = { + region, + credentials: { + accessKeyId, + secretAccessKey, + }, + forcePathStyle: true, + }; + + if (endpoint) { + config.endpoint = endpoint; + } + + this.client = new S3Client(config); + } + + /** + * Verifies bucket access and credentials. + * @throws {WarpTokenError} If authentication fails + * @throws {Error} If bucket not found or network error + */ + async verify(): Promise { + try { + const command = new HeadBucketCommand({ + Bucket: this.bucket, + }); + await this.client.send(command); + } catch (error: any) { + if ( + error.name === "InvalidAccessKeyId" || + error.name === "SignatureDoesNotMatch" || + error.name === "InvalidClientTokenId" + ) { + throw new WarpTokenError(error); + } + if (error.name === "NoSuchBucket") { + throw new Error(`Bucket not found: ${this.bucket}`); + } + if (error.message?.includes("getaddrinfo") || error.message?.includes("fetch failed")) { + throw new Error("Network connection failed. Please check your internet connection."); + } + throw error; + } + } + + /** + * Opens a file for reading. + * @param file - File information + * @returns FileReader instance for reading file content + */ + async open(file: FileInfo): Promise { + const key = joinPath(file.path, file.name).substring(1); // Remove leading / + return new S3FileReader(this.client, this.bucket, key); + } + + /** + * Opens a directory (returns a new FileSystem scoped to that directory). + * @param path - Directory path relative to current basePath + * @returns New S3FileSystem instance scoped to the directory + */ + async openDir(path: string): Promise { + const newBasePath = joinPath(this.basePath, path); + return new S3FileSystem( + this.bucket, + this.region, + "", // These won't be used since we're reusing the client + "", + undefined, + newBasePath + ); + } + + /** + * Creates a file for writing. + * @param path - File path relative to current basePath + * @param opts - Optional file creation options (modifiedDate) + * @returns FileWriter instance for writing file content + */ + async create(path: string, opts?: FileCreateOptions): Promise { + const key = joinPath(this.basePath, path).substring(1); // Remove leading / + return new S3FileWriter(this.client, this.bucket, key, opts?.modifiedDate); + } + + /** + * Creates a directory (no-op for S3, directories are implicit). + * @param _path - Directory path (unused) + * @param _opts - Optional creation options (unused) + */ + async createDir(_path: string, _opts?: FileCreateOptions): Promise { + // No-op: S3 doesn't require explicit directory creation + return Promise.resolve(); + } + + /** + * Deletes a file from S3. + * This operation is idempotent - deleting a non-existent file succeeds. + * @param path - File path relative to current basePath + */ + async delete(path: string): Promise { + try { + const key = joinPath(this.basePath, path).substring(1); // Remove leading / + const command = new DeleteObjectCommand({ + Bucket: this.bucket, + Key: key, + }); + await this.client.send(command); + } catch (error: any) { + // S3 delete is idempotent - if the key doesn't exist, it succeeds + if (error.name === "NoSuchKey") { + return; + } + throw error; + } + } + + /** + * Lists files in the current directory. + * Handles pagination automatically for large directories. + * @returns Array of FileInfo objects for files in current directory + * @throws {Error} If permission denied or other S3 error + */ + async list(): Promise { + const prefix = this.basePath === "/" ? "" : this.basePath.substring(1); + const files: FileInfo[] = []; + let continuationToken: string | undefined; + + try { + do { + const command = new ListObjectsV2Command({ + Bucket: this.bucket, + Prefix: prefix, + Delimiter: "/", + ContinuationToken: continuationToken, + }); + + const response = await this.client.send(command); + + if (response.Contents) { + for (const object of response.Contents) { + if (!object.Key) continue; + + // Skip the directory marker itself + if (object.Key === prefix || object.Key.endsWith("/")) continue; + + const name = object.Key.substring(prefix.length); + const lastModified = object.LastModified?.getTime() || Date.now(); + + files.push({ + name, + path: this.basePath, + size: object.Size || 0, + digest: object.ETag?.replace(/"/g, "") || "", + createtime: lastModified, + updatetime: lastModified, + }); + } + } + + continuationToken = response.NextContinuationToken; + } while (continuationToken); + + return files; + } catch (error: any) { + if (error.name === "AccessDenied") { + throw new Error(`Permission denied. Check your IAM permissions for bucket: ${this.bucket}`); + } + throw error; + } + } + + /** + * Gets the S3 console URL for the current directory. + * @returns URL to S3 console for this bucket/prefix + */ + async getDirUrl(): Promise { + const prefix = this.basePath === "/" ? "" : this.basePath.substring(1); + return `https://s3.console.aws.amazon.com/s3/buckets/${this.bucket}?prefix=${encodeURIComponent(prefix)}®ion=${this.region}`; + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e5ee772c7..1d2d31566 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: '@arco-design/web-react': specifier: ^2.66.7 version: 2.66.7(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@aws-sdk/client-s3': + specifier: ^3.981.0 + version: 3.981.0 '@dnd-kit/core': specifier: ^6.3.1 version: 6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -238,6 +241,173 @@ packages: '@asamuzakjp/css-color@3.2.0': resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} + '@aws-crypto/crc32@5.2.0': + resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/crc32c@5.2.0': + resolution: {integrity: sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==} + + '@aws-crypto/sha1-browser@5.2.0': + resolution: {integrity: sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==} + + '@aws-crypto/sha256-browser@5.2.0': + resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} + + '@aws-crypto/sha256-js@5.2.0': + resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/supports-web-crypto@5.2.0': + resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} + + '@aws-crypto/util@5.2.0': + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} + + '@aws-sdk/client-s3@3.981.0': + resolution: {integrity: sha512-zX3Xqm7V30J1D2II7WBL23SyqIIMD0wMzpiE+VosBxH6fAeXgrjIwSudCypNgnE1EK9OZoZMT3mJtkbUqUDdaA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/client-sso@3.980.0': + resolution: {integrity: sha512-AhNXQaJ46C1I+lQ+6Kj+L24il5K9lqqIanJd8lMszPmP7bLnmX0wTKK0dxywcvrLdij3zhWttjAKEBNgLtS8/A==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/core@3.973.5': + resolution: {integrity: sha512-IMM7xGfLGW6lMvubsA4j6BHU5FPgGAxoQ/NA63KqNLMwTS+PeMBcx8DPHL12Vg6yqOZnqok9Mu4H2BdQyq7gSA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/crc64-nvme@3.972.0': + resolution: {integrity: sha512-ThlLhTqX68jvoIVv+pryOdb5coP1cX1/MaTbB9xkGDCbWbsqQcLqzPxuSoW1DCnAAIacmXCWpzUNOB9pv+xXQw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-env@3.972.3': + resolution: {integrity: sha512-OBYNY4xQPq7Rx+oOhtyuyO0AQvdJSpXRg7JuPNBJH4a1XXIzJQl4UHQTPKZKwfJXmYLpv4+OkcFen4LYmDPd3g==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-http@3.972.5': + resolution: {integrity: sha512-GpvBgEmSZPvlDekd26Zi+XsI27Qz7y0utUx0g2fSTSiDzhnd1FSa1owuodxR0BcUKNL7U2cOVhhDxgZ4iSoPVg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-ini@3.972.3': + resolution: {integrity: sha512-rMQAIxstP7cLgYfsRGrGOlpyMl0l8JL2mcke3dsIPLWke05zKOFyR7yoJzWCsI/QiIxjRbxpvPiAeKEA6CoYkg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-login@3.972.3': + resolution: {integrity: sha512-Gc3O91iVvA47kp2CLIXOwuo5ffo1cIpmmyIewcYjAcvurdFHQ8YdcBe1KHidnbbBO4/ZtywGBACsAX5vr3UdoA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-node@3.972.4': + resolution: {integrity: sha512-UwerdzosMSY7V5oIZm3NsMDZPv2aSVzSkZxYxIOWHBeKTZlUqW7XpHtJMZ4PZpJ+HMRhgP+MDGQx4THndgqJfQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-process@3.972.3': + resolution: {integrity: sha512-xkSY7zjRqeVc6TXK2xr3z1bTLm0wD8cj3lAkproRGaO4Ku7dPlKy843YKnHrUOUzOnMezdZ4xtmFc0eKIDTo2w==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-sso@3.972.3': + resolution: {integrity: sha512-8Ww3F5Ngk8dZ6JPL/V5LhCU1BwMfQd3tLdoEuzaewX8FdnT633tPr+KTHySz9FK7fFPcz5qG3R5edVEhWQD4AA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.972.3': + resolution: {integrity: sha512-62VufdcH5rRfiRKZRcf1wVbbt/1jAntMj1+J0qAd+r5pQRg2t0/P9/Rz16B1o5/0Se9lVL506LRjrhIJAhYBfA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-bucket-endpoint@3.972.3': + resolution: {integrity: sha512-fmbgWYirF67YF1GfD7cg5N6HHQ96EyRNx/rDIrTF277/zTWVuPI2qS/ZHgofwR1NZPe/NWvoppflQY01LrbVLg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-expect-continue@3.972.3': + resolution: {integrity: sha512-4msC33RZsXQpUKR5QR4HnvBSNCPLGHmB55oDiROqqgyOc+TOfVu2xgi5goA7ms6MdZLeEh2905UfWMnMMF4mRg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-flexible-checksums@3.972.3': + resolution: {integrity: sha512-MkNGJ6qB9kpsLwL18kC/ZXppsJbftHVGCisqpEVbTQsum8CLYDX1Bmp/IvhRGNxsqCO2w9/4PwhDKBjG3Uvr4Q==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-host-header@3.972.3': + resolution: {integrity: sha512-aknPTb2M+G3s+0qLCx4Li/qGZH8IIYjugHMv15JTYMe6mgZO8VBpYgeGYsNMGCqCZOcWzuf900jFBG5bopfzmA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-location-constraint@3.972.3': + resolution: {integrity: sha512-nIg64CVrsXp67vbK0U1/Is8rik3huS3QkRHn2DRDx4NldrEFMgdkZGI/+cZMKD9k4YOS110Dfu21KZLHrFA/1g==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-logger@3.972.3': + resolution: {integrity: sha512-Ftg09xNNRqaz9QNzlfdQWfpqMCJbsQdnZVJP55jfhbKi1+FTWxGuvfPoBhDHIovqWKjqbuiew3HuhxbJ0+OjgA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-recursion-detection@3.972.3': + resolution: {integrity: sha512-PY57QhzNuXHnwbJgbWYTrqIDHYSeOlhfYERTAuc16LKZpTZRJUjzBFokp9hF7u1fuGeE3D70ERXzdbMBOqQz7Q==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-sdk-s3@3.972.5': + resolution: {integrity: sha512-3IgeIDiQ15tmMBFIdJ1cTy3A9rXHGo+b9p22V38vA3MozeMyVC8VmCYdDLA0iMWo4VHA9LDJTgCM0+xU3wjBOg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-ssec@3.972.3': + resolution: {integrity: sha512-dU6kDuULN3o3jEHcjm0c4zWJlY1zWVkjG9NPe9qxYLLpcbdj5kRYBS2DdWYD+1B9f910DezRuws7xDEqKkHQIg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-user-agent@3.972.5': + resolution: {integrity: sha512-TVZQ6PWPwQbahUI8V+Er+gS41ctIawcI/uMNmQtQ7RMcg3JYn6gyKAFKUb3HFYx2OjYlx1u11sETSwwEUxVHTg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/nested-clients@3.980.0': + resolution: {integrity: sha512-/dONY5xc5/CCKzOqHZCTidtAR4lJXWkGefXvTRKdSKMGaYbbKsxDckisd6GfnvPSLxWtvQzwgRGRutMRoYUApQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/region-config-resolver@3.972.3': + resolution: {integrity: sha512-v4J8qYAWfOMcZ4MJUyatntOicTzEMaU7j3OpkRCGGFSL2NgXQ5VbxauIyORA+pxdKZ0qQG2tCQjQjZDlXEC3Ow==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/signature-v4-multi-region@3.981.0': + resolution: {integrity: sha512-T/+h9df0DALAXXP+YfZ8bgmH6cEN7HAg6BqHe3t38GhHgQ1HULXwK5XMhiLWiHpytDdhLqiVH41SRgW8ynBl6Q==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/token-providers@3.980.0': + resolution: {integrity: sha512-1nFileg1wAgDmieRoj9dOawgr2hhlh7xdvcH57b1NnqfPaVlcqVJyPc6k3TLDUFPY69eEwNxdGue/0wIz58vjA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/types@3.973.1': + resolution: {integrity: sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-arn-parser@3.972.2': + resolution: {integrity: sha512-VkykWbqMjlSgBFDyrY3nOSqupMc6ivXuGmvci6Q3NnLq5kC+mKQe2QBZ4nrWRE/jqOxeFP2uYzLtwncYYcvQDg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-endpoints@3.980.0': + resolution: {integrity: sha512-AjKBNEc+rjOZQE1HwcD9aCELqg1GmUj1rtICKuY8cgwB73xJ4U/kNyqKKpN2k9emGqlfDY2D8itIp/vDc6OKpw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-endpoints@3.981.0': + resolution: {integrity: sha512-a8nXh/H3/4j+sxhZk+N3acSDlgwTVSZbX9i55dx41gI1H+geuonuRG+Shv3GZsCb46vzc08RK2qC78ypO8uRlg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-locate-window@3.965.4': + resolution: {integrity: sha512-H1onv5SkgPBK2P6JR2MjGgbOnttoNzSPIRoeZTNPZYyaplwGg50zS3amXvXqF0/qfXpWEC9rLWU564QTB9bSog==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-user-agent-browser@3.972.3': + resolution: {integrity: sha512-JurOwkRUcXD/5MTDBcqdyQ9eVedtAsZgw5rBwktsPTN7QtPiS2Ld1jkJepNgYoCufz1Wcut9iup7GJDoIHp8Fw==} + + '@aws-sdk/util-user-agent-node@3.972.3': + resolution: {integrity: sha512-gqG+02/lXQtO0j3US6EVnxtwwoXQC5l2qkhLCrqUrqdtcQxV7FDMbm9wLjKqoronSHyELGTjbFKK/xV5q1bZNA==} + engines: {node: '>=20.0.0'} + peerDependencies: + aws-crt: '>=1.0.0' + peerDependenciesMeta: + aws-crt: + optional: true + + '@aws-sdk/xml-builder@3.972.3': + resolution: {integrity: sha512-bCk63RsBNCWW4tt5atv5Sbrh+3J3e8YzgyF6aZb1JeXcdzG4k5SlPLeTMFOIXFuuFHIwgphUhn4i3uS/q49eww==} + engines: {node: '>=20.0.0'} + + '@aws/lambda-invoke-store@0.2.3': + resolution: {integrity: sha512-oLvsaPMTBejkkmHhjf09xTgk71mOqyr/409NKhRIL08If7AhVfUsJhVsx386uJaqNd42v9kWamQ9lFbkoC2dYw==} + engines: {node: '>=18.0.0'} + '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -905,56 +1075,67 @@ packages: resolution: {integrity: sha512-+xmiDGGaSfIIOXMzkhJ++Oa0Gwvl9oXUeIiwarsdRXSe27HUIvjbSIpPxvnNsRebsNdUo7uAiQVgBD1hVriwSQ==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.44.2': resolution: {integrity: sha512-bDHvhzOfORk3wt8yxIra8N4k/N0MnKInCW5OGZaeDYa/hMrdPaJzo7CSkjKZqX4JFUWjUGm88lI6QJLCM7lDrA==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.44.2': resolution: {integrity: sha512-NMsDEsDiYghTbeZWEGnNi4F0hSbGnsuOG+VnNvxkKg0IGDvFh7UVpM/14mnMwxRxUf9AdAVJgHPvKXf6FpMB7A==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.44.2': resolution: {integrity: sha512-lb5bxXnxXglVq+7imxykIp5xMq+idehfl+wOgiiix0191av84OqbjUED+PRC5OA8eFJYj5xAGcpAZ0pF2MnW+A==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-loongarch64-gnu@4.44.2': resolution: {integrity: sha512-Yl5Rdpf9pIc4GW1PmkUGHdMtbx0fBLE1//SxDmuf3X0dUC57+zMepow2LK0V21661cjXdTn8hO2tXDdAWAqE5g==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-powerpc64le-gnu@4.44.2': resolution: {integrity: sha512-03vUDH+w55s680YYryyr78jsO1RWU9ocRMaeV2vMniJJW/6HhoTBwyyiiTPVHNWLnhsnwcQ0oH3S9JSBEKuyqw==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-gnu@4.44.2': resolution: {integrity: sha512-iYtAqBg5eEMG4dEfVlkqo05xMOk6y/JXIToRca2bAWuqjrJYJlx/I7+Z+4hSrsWU8GdJDFPL4ktV3dy4yBSrzg==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.44.2': resolution: {integrity: sha512-e6vEbgaaqz2yEHqtkPXa28fFuBGmUJ0N2dOJK8YUfijejInt9gfCSA7YDdJ4nYlv67JfP3+PSWFX4IVw/xRIPg==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.44.2': resolution: {integrity: sha512-evFOtkmVdY3udE+0QKrV5wBx7bKI0iHz5yEVx5WqDJkxp9YQefy4Mpx3RajIVcM6o7jxTvVd/qpC1IXUhGc1Mw==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.44.2': resolution: {integrity: sha512-/bXb0bEsWMyEkIsUL2Yt5nFB5naLAwyOWMEviQfQY1x3l5WsLKgvZf66TM7UTfED6erckUVUJQ/jJ1FSpm3pRQ==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.44.2': resolution: {integrity: sha512-3D3OB1vSSBXmkGEZR27uiMRNiwN08/RVAcBKwhUYPaiZ8bcvdeEwWPvbnXvvXHY+A/7xluzcN+kaiOFNiOZwWg==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-win32-arm64-msvc@4.44.2': resolution: {integrity: sha512-VfU0fsMK+rwdK8mwODqYeM2hDrF2WiHaSmCBrS7gColkQft95/8tphyzv2EupVxn3iE0FI78wzffoULH1G+dkw==} @@ -985,21 +1166,25 @@ packages: resolution: {integrity: sha512-n7UGSBzv7PiX+V1Q2bY3S1XWyN3RCykCQUgfhZ+xWietCM/1349jgN7DoXKPllqlof1GPGBjziHU0sQZTC4tag==} cpu: [arm64] os: [linux] + libc: [glibc] '@rspack/binding-linux-arm64-musl@1.6.1': resolution: {integrity: sha512-P7nx0jsKxx7g3QAnH9UnJDGVgs1M2H7ZQl68SRyrs42TKOd9Md22ynoMIgCK1zoy+skssU6MhWptluSggXqSrA==} cpu: [arm64] os: [linux] + libc: [musl] '@rspack/binding-linux-x64-gnu@1.6.1': resolution: {integrity: sha512-SdiurC1bV/QHnj7rmrBYJLdsat3uUDWl9KjkVjEbtc8kQV0Ri4/vZRH0nswgzx7hZNY2j0jYuCm5O8+3qeJEMg==} cpu: [x64] os: [linux] + libc: [glibc] '@rspack/binding-linux-x64-musl@1.6.1': resolution: {integrity: sha512-JoSJu29nV+auOePhe8x2Fzqxiga1YGNcOMWKJ5Uj8rHBZ8FPAiiE+CpLG8TwfpHsivojrY/sy6fE8JldYLV5TQ==} cpu: [x64] os: [linux] + libc: [musl] '@rspack/binding-wasm32-wasi@1.6.1': resolution: {integrity: sha512-u5NiSHxM7LtIo4cebq/hQPJ9o39u127am3eVJHDzdmBVhTYYO5l7XVUnFmcU8hNHuj/4lJzkFviWFbf3SaRSYA==} @@ -1048,6 +1233,222 @@ packages: resolution: {integrity: sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==} engines: {node: '>=16.0.0'} + '@smithy/abort-controller@4.2.8': + resolution: {integrity: sha512-peuVfkYHAmS5ybKxWcfraK7WBBP0J+rkfUcbHJJKQ4ir3UAUNQI+Y4Vt/PqSzGqgloJ5O1dk7+WzNL8wcCSXbw==} + engines: {node: '>=18.0.0'} + + '@smithy/chunked-blob-reader-native@4.2.1': + resolution: {integrity: sha512-lX9Ay+6LisTfpLid2zZtIhSEjHMZoAR5hHCR4H7tBz/Zkfr5ea8RcQ7Tk4mi0P76p4cN+Btz16Ffno7YHpKXnQ==} + engines: {node: '>=18.0.0'} + + '@smithy/chunked-blob-reader@5.2.0': + resolution: {integrity: sha512-WmU0TnhEAJLWvfSeMxBNe5xtbselEO8+4wG0NtZeL8oR21WgH1xiO37El+/Y+H/Ie4SCwBy3MxYWmOYaGgZueA==} + engines: {node: '>=18.0.0'} + + '@smithy/config-resolver@4.4.6': + resolution: {integrity: sha512-qJpzYC64kaj3S0fueiu3kXm8xPrR3PcXDPEgnaNMRn0EjNSZFoFjvbUp0YUDsRhN1CB90EnHJtbxWKevnH99UQ==} + engines: {node: '>=18.0.0'} + + '@smithy/core@3.22.1': + resolution: {integrity: sha512-x3ie6Crr58MWrm4viHqqy2Du2rHYZjwu8BekasrQx4ca+Y24dzVAwq3yErdqIbc2G3I0kLQA13PQ+/rde+u65g==} + engines: {node: '>=18.0.0'} + + '@smithy/credential-provider-imds@4.2.8': + resolution: {integrity: sha512-FNT0xHS1c/CPN8upqbMFP83+ul5YgdisfCfkZ86Jh2NSmnqw/AJ6x5pEogVCTVvSm7j9MopRU89bmDelxuDMYw==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-codec@4.2.8': + resolution: {integrity: sha512-jS/O5Q14UsufqoGhov7dHLOPCzkYJl9QDzusI2Psh4wyYx/izhzvX9P4D69aTxcdfVhEPhjK+wYyn/PzLjKbbw==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-browser@4.2.8': + resolution: {integrity: sha512-MTfQT/CRQz5g24ayXdjg53V0mhucZth4PESoA5IhvaWVDTOQLfo8qI9vzqHcPsdd2v6sqfTYqF5L/l+pea5Uyw==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-config-resolver@4.3.8': + resolution: {integrity: sha512-ah12+luBiDGzBruhu3efNy1IlbwSEdNiw8fOZksoKoWW1ZHvO/04MQsdnws/9Aj+5b0YXSSN2JXKy/ClIsW8MQ==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-node@4.2.8': + resolution: {integrity: sha512-cYpCpp29z6EJHa5T9WL0KAlq3SOKUQkcgSoeRfRVwjGgSFl7Uh32eYGt7IDYCX20skiEdRffyDpvF2efEZPC0A==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-universal@4.2.8': + resolution: {integrity: sha512-iJ6YNJd0bntJYnX6s52NC4WFYcZeKrPUr1Kmmr5AwZcwCSzVpS7oavAmxMR7pMq7V+D1G4s9F5NJK0xwOsKAlQ==} + engines: {node: '>=18.0.0'} + + '@smithy/fetch-http-handler@5.3.9': + resolution: {integrity: sha512-I4UhmcTYXBrct03rwzQX1Y/iqQlzVQaPxWjCjula++5EmWq9YGBrx6bbGqluGc1f0XEfhSkiY4jhLgbsJUMKRA==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-blob-browser@4.2.9': + resolution: {integrity: sha512-m80d/iicI7DlBDxyQP6Th7BW/ejDGiF0bgI754+tiwK0lgMkcaIBgvwwVc7OFbY4eUzpGtnig52MhPAEJ7iNYg==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-node@4.2.8': + resolution: {integrity: sha512-7ZIlPbmaDGxVoxErDZnuFG18WekhbA/g2/i97wGj+wUBeS6pcUeAym8u4BXh/75RXWhgIJhyC11hBzig6MljwA==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-stream-node@4.2.8': + resolution: {integrity: sha512-v0FLTXgHrTeheYZFGhR+ehX5qUm4IQsjAiL9qehad2cyjMWcN2QG6/4mSwbSgEQzI7jwfoXj7z4fxZUx/Mhj2w==} + engines: {node: '>=18.0.0'} + + '@smithy/invalid-dependency@4.2.8': + resolution: {integrity: sha512-N9iozRybwAQ2dn9Fot9kI6/w9vos2oTXLhtK7ovGqwZjlOcxu6XhPlpLpC+INsxktqHinn5gS2DXDjDF2kG5sQ==} + engines: {node: '>=18.0.0'} + + '@smithy/is-array-buffer@2.2.0': + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} + + '@smithy/is-array-buffer@4.2.0': + resolution: {integrity: sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==} + engines: {node: '>=18.0.0'} + + '@smithy/md5-js@4.2.8': + resolution: {integrity: sha512-oGMaLj4tVZzLi3itBa9TCswgMBr7k9b+qKYowQ6x1rTyTuO1IU2YHdHUa+891OsOH+wCsH7aTPRsTJO3RMQmjQ==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-content-length@4.2.8': + resolution: {integrity: sha512-RO0jeoaYAB1qBRhfVyq0pMgBoUK34YEJxVxyjOWYZiOKOq2yMZ4MnVXMZCUDenpozHue207+9P5ilTV1zeda0A==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-endpoint@4.4.13': + resolution: {integrity: sha512-x6vn0PjYmGdNuKh/juUJJewZh7MoQ46jYaJ2mvekF4EesMuFfrl4LaW/k97Zjf8PTCPQmPgMvwewg7eNoH9n5w==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-retry@4.4.30': + resolution: {integrity: sha512-CBGyFvN0f8hlnqKH/jckRDz78Snrp345+PVk8Ux7pnkUCW97Iinse59lY78hBt04h1GZ6hjBN94BRwZy1xC8Bg==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-serde@4.2.9': + resolution: {integrity: sha512-eMNiej0u/snzDvlqRGSN3Vl0ESn3838+nKyVfF2FKNXFbi4SERYT6PR392D39iczngbqqGG0Jl1DlCnp7tBbXQ==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-stack@4.2.8': + resolution: {integrity: sha512-w6LCfOviTYQjBctOKSwy6A8FIkQy7ICvglrZFl6Bw4FmcQ1Z420fUtIhxaUZZshRe0VCq4kvDiPiXrPZAe8oRA==} + engines: {node: '>=18.0.0'} + + '@smithy/node-config-provider@4.3.8': + resolution: {integrity: sha512-aFP1ai4lrbVlWjfpAfRSL8KFcnJQYfTl5QxLJXY32vghJrDuFyPZ6LtUL+JEGYiFRG1PfPLHLoxj107ulncLIg==} + engines: {node: '>=18.0.0'} + + '@smithy/node-http-handler@4.4.9': + resolution: {integrity: sha512-KX5Wml5mF+luxm1szW4QDz32e3NObgJ4Fyw+irhph4I/2geXwUy4jkIMUs5ZPGflRBeR6BUkC2wqIab4Llgm3w==} + engines: {node: '>=18.0.0'} + + '@smithy/property-provider@4.2.8': + resolution: {integrity: sha512-EtCTbyIveCKeOXDSWSdze3k612yCPq1YbXsbqX3UHhkOSW8zKsM9NOJG5gTIya0vbY2DIaieG8pKo1rITHYL0w==} + engines: {node: '>=18.0.0'} + + '@smithy/protocol-http@5.3.8': + resolution: {integrity: sha512-QNINVDhxpZ5QnP3aviNHQFlRogQZDfYlCkQT+7tJnErPQbDhysondEjhikuANxgMsZrkGeiAxXy4jguEGsDrWQ==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-builder@4.2.8': + resolution: {integrity: sha512-Xr83r31+DrE8CP3MqPgMJl+pQlLLmOfiEUnoyAlGzzJIrEsbKsPy1hqH0qySaQm4oWrCBlUqRt+idEgunKB+iw==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-parser@4.2.8': + resolution: {integrity: sha512-vUurovluVy50CUlazOiXkPq40KGvGWSdmusa3130MwrR1UNnNgKAlj58wlOe61XSHRpUfIIh6cE0zZ8mzKaDPA==} + engines: {node: '>=18.0.0'} + + '@smithy/service-error-classification@4.2.8': + resolution: {integrity: sha512-mZ5xddodpJhEt3RkCjbmUQuXUOaPNTkbMGR0bcS8FE0bJDLMZlhmpgrvPNCYglVw5rsYTpSnv19womw9WWXKQQ==} + engines: {node: '>=18.0.0'} + + '@smithy/shared-ini-file-loader@4.4.3': + resolution: {integrity: sha512-DfQjxXQnzC5UbCUPeC3Ie8u+rIWZTvuDPAGU/BxzrOGhRvgUanaP68kDZA+jaT3ZI+djOf+4dERGlm9mWfFDrg==} + engines: {node: '>=18.0.0'} + + '@smithy/signature-v4@5.3.8': + resolution: {integrity: sha512-6A4vdGj7qKNRF16UIcO8HhHjKW27thsxYci+5r/uVRkdcBEkOEiY8OMPuydLX4QHSrJqGHPJzPRwwVTqbLZJhg==} + engines: {node: '>=18.0.0'} + + '@smithy/smithy-client@4.11.2': + resolution: {integrity: sha512-SCkGmFak/xC1n7hKRsUr6wOnBTJ3L22Qd4e8H1fQIuKTAjntwgU8lrdMe7uHdiT2mJAOWA/60qaW9tiMu69n1A==} + engines: {node: '>=18.0.0'} + + '@smithy/types@4.12.0': + resolution: {integrity: sha512-9YcuJVTOBDjg9LWo23Qp0lTQ3D7fQsQtwle0jVfpbUHy9qBwCEgKuVH4FqFB3VYu0nwdHKiEMA+oXz7oV8X1kw==} + engines: {node: '>=18.0.0'} + + '@smithy/url-parser@4.2.8': + resolution: {integrity: sha512-NQho9U68TGMEU639YkXnVMV3GEFFULmmaWdlu1E9qzyIePOHsoSnagTGSDv1Zi8DCNN6btxOSdgmy5E/hsZwhA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-base64@4.3.0': + resolution: {integrity: sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-browser@4.2.0': + resolution: {integrity: sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-node@4.2.1': + resolution: {integrity: sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-buffer-from@2.2.0': + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} + engines: {node: '>=14.0.0'} + + '@smithy/util-buffer-from@4.2.0': + resolution: {integrity: sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==} + engines: {node: '>=18.0.0'} + + '@smithy/util-config-provider@4.2.0': + resolution: {integrity: sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-browser@4.3.29': + resolution: {integrity: sha512-nIGy3DNRmOjaYaaKcQDzmWsro9uxlaqUOhZDHQed9MW/GmkBZPtnU70Pu1+GT9IBmUXwRdDuiyaeiy9Xtpn3+Q==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-node@4.2.32': + resolution: {integrity: sha512-7dtFff6pu5fsjqrVve0YMhrnzJtccCWDacNKOkiZjJ++fmjGExmmSu341x+WU6Oc1IccL7lDuaUj7SfrHpWc5Q==} + engines: {node: '>=18.0.0'} + + '@smithy/util-endpoints@3.2.8': + resolution: {integrity: sha512-8JaVTn3pBDkhZgHQ8R0epwWt+BqPSLCjdjXXusK1onwJlRuN69fbvSK66aIKKO7SwVFM6x2J2ox5X8pOaWcUEw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-hex-encoding@4.2.0': + resolution: {integrity: sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-middleware@4.2.8': + resolution: {integrity: sha512-PMqfeJxLcNPMDgvPbbLl/2Vpin+luxqTGPpW3NAQVLbRrFRzTa4rNAASYeIGjRV9Ytuhzny39SpyU04EQreF+A==} + engines: {node: '>=18.0.0'} + + '@smithy/util-retry@4.2.8': + resolution: {integrity: sha512-CfJqwvoRY0kTGe5AkQokpURNCT1u/MkRzMTASWMPPo2hNSnKtF1D45dQl3DE2LKLr4m+PW9mCeBMJr5mCAVThg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-stream@4.5.11': + resolution: {integrity: sha512-lKmZ0S/3Qj2OF5H1+VzvDLb6kRxGzZHq6f3rAsoSu5cTLGsn3v3VQBA8czkNNXlLjoFEtVu3OQT2jEeOtOE2CA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-uri-escape@4.2.0': + resolution: {integrity: sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-utf8@2.3.0': + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@4.2.0': + resolution: {integrity: sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-waiter@4.2.8': + resolution: {integrity: sha512-n+lahlMWk+aejGuax7DPWtqav8HYnWxQwR+LCG2BgCUmaGcTe9qZCFsmw8TMg9iG75HOwhrJCX9TCJRLH+Yzqg==} + engines: {node: '>=18.0.0'} + + '@smithy/uuid@1.1.0': + resolution: {integrity: sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==} + engines: {node: '>=18.0.0'} + '@swc/helpers@0.5.17': resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} @@ -1646,6 +2047,9 @@ packages: bonjour-service@1.3.0: resolution: {integrity: sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==} + bowser@2.13.1: + resolution: {integrity: sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw==} + brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} @@ -2275,6 +2679,10 @@ packages: resolution: {integrity: sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==} hasBin: true + fast-xml-parser@5.3.4: + resolution: {integrity: sha512-EFd6afGmXlCx8H8WTZHhAoDaWaGyuIBoZJ2mknrNxug+aZKjkp0a0dlars9Izl+jF+7Gu1/5f/2h68cQpe0IiA==} + hasBin: true + fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -3780,6 +4188,9 @@ packages: strnum@1.1.2: resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==} + strnum@2.1.2: + resolution: {integrity: sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==} + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -4394,6 +4805,499 @@ snapshots: '@csstools/css-tokenizer': 3.0.4 lru-cache: 10.4.3 + '@aws-crypto/crc32@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.1 + tslib: 2.8.1 + + '@aws-crypto/crc32c@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.1 + tslib: 2.8.1 + + '@aws-crypto/sha1-browser@5.2.0': + dependencies: + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.1 + '@aws-sdk/util-locate-window': 3.965.4 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-crypto/sha256-browser@5.2.0': + dependencies: + '@aws-crypto/sha256-js': 5.2.0 + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.1 + '@aws-sdk/util-locate-window': 3.965.4 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-crypto/sha256-js@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.1 + tslib: 2.8.1 + + '@aws-crypto/supports-web-crypto@5.2.0': + dependencies: + tslib: 2.8.1 + + '@aws-crypto/util@5.2.0': + dependencies: + '@aws-sdk/types': 3.973.1 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-sdk/client-s3@3.981.0': + dependencies: + '@aws-crypto/sha1-browser': 5.2.0 + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.973.5 + '@aws-sdk/credential-provider-node': 3.972.4 + '@aws-sdk/middleware-bucket-endpoint': 3.972.3 + '@aws-sdk/middleware-expect-continue': 3.972.3 + '@aws-sdk/middleware-flexible-checksums': 3.972.3 + '@aws-sdk/middleware-host-header': 3.972.3 + '@aws-sdk/middleware-location-constraint': 3.972.3 + '@aws-sdk/middleware-logger': 3.972.3 + '@aws-sdk/middleware-recursion-detection': 3.972.3 + '@aws-sdk/middleware-sdk-s3': 3.972.5 + '@aws-sdk/middleware-ssec': 3.972.3 + '@aws-sdk/middleware-user-agent': 3.972.5 + '@aws-sdk/region-config-resolver': 3.972.3 + '@aws-sdk/signature-v4-multi-region': 3.981.0 + '@aws-sdk/types': 3.973.1 + '@aws-sdk/util-endpoints': 3.981.0 + '@aws-sdk/util-user-agent-browser': 3.972.3 + '@aws-sdk/util-user-agent-node': 3.972.3 + '@smithy/config-resolver': 4.4.6 + '@smithy/core': 3.22.1 + '@smithy/eventstream-serde-browser': 4.2.8 + '@smithy/eventstream-serde-config-resolver': 4.3.8 + '@smithy/eventstream-serde-node': 4.2.8 + '@smithy/fetch-http-handler': 5.3.9 + '@smithy/hash-blob-browser': 4.2.9 + '@smithy/hash-node': 4.2.8 + '@smithy/hash-stream-node': 4.2.8 + '@smithy/invalid-dependency': 4.2.8 + '@smithy/md5-js': 4.2.8 + '@smithy/middleware-content-length': 4.2.8 + '@smithy/middleware-endpoint': 4.4.13 + '@smithy/middleware-retry': 4.4.30 + '@smithy/middleware-serde': 4.2.9 + '@smithy/middleware-stack': 4.2.8 + '@smithy/node-config-provider': 4.3.8 + '@smithy/node-http-handler': 4.4.9 + '@smithy/protocol-http': 5.3.8 + '@smithy/smithy-client': 4.11.2 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-body-length-node': 4.2.1 + '@smithy/util-defaults-mode-browser': 4.3.29 + '@smithy/util-defaults-mode-node': 4.2.32 + '@smithy/util-endpoints': 3.2.8 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-retry': 4.2.8 + '@smithy/util-stream': 4.5.11 + '@smithy/util-utf8': 4.2.0 + '@smithy/util-waiter': 4.2.8 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/client-sso@3.980.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.973.5 + '@aws-sdk/middleware-host-header': 3.972.3 + '@aws-sdk/middleware-logger': 3.972.3 + '@aws-sdk/middleware-recursion-detection': 3.972.3 + '@aws-sdk/middleware-user-agent': 3.972.5 + '@aws-sdk/region-config-resolver': 3.972.3 + '@aws-sdk/types': 3.973.1 + '@aws-sdk/util-endpoints': 3.980.0 + '@aws-sdk/util-user-agent-browser': 3.972.3 + '@aws-sdk/util-user-agent-node': 3.972.3 + '@smithy/config-resolver': 4.4.6 + '@smithy/core': 3.22.1 + '@smithy/fetch-http-handler': 5.3.9 + '@smithy/hash-node': 4.2.8 + '@smithy/invalid-dependency': 4.2.8 + '@smithy/middleware-content-length': 4.2.8 + '@smithy/middleware-endpoint': 4.4.13 + '@smithy/middleware-retry': 4.4.30 + '@smithy/middleware-serde': 4.2.9 + '@smithy/middleware-stack': 4.2.8 + '@smithy/node-config-provider': 4.3.8 + '@smithy/node-http-handler': 4.4.9 + '@smithy/protocol-http': 5.3.8 + '@smithy/smithy-client': 4.11.2 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-body-length-node': 4.2.1 + '@smithy/util-defaults-mode-browser': 4.3.29 + '@smithy/util-defaults-mode-node': 4.2.32 + '@smithy/util-endpoints': 3.2.8 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-retry': 4.2.8 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/core@3.973.5': + dependencies: + '@aws-sdk/types': 3.973.1 + '@aws-sdk/xml-builder': 3.972.3 + '@smithy/core': 3.22.1 + '@smithy/node-config-provider': 4.3.8 + '@smithy/property-provider': 4.2.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/signature-v4': 5.3.8 + '@smithy/smithy-client': 4.11.2 + '@smithy/types': 4.12.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/crc64-nvme@3.972.0': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-env@3.972.3': + dependencies: + '@aws-sdk/core': 3.973.5 + '@aws-sdk/types': 3.973.1 + '@smithy/property-provider': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-http@3.972.5': + dependencies: + '@aws-sdk/core': 3.973.5 + '@aws-sdk/types': 3.973.1 + '@smithy/fetch-http-handler': 5.3.9 + '@smithy/node-http-handler': 4.4.9 + '@smithy/property-provider': 4.2.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/smithy-client': 4.11.2 + '@smithy/types': 4.12.0 + '@smithy/util-stream': 4.5.11 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-ini@3.972.3': + dependencies: + '@aws-sdk/core': 3.973.5 + '@aws-sdk/credential-provider-env': 3.972.3 + '@aws-sdk/credential-provider-http': 3.972.5 + '@aws-sdk/credential-provider-login': 3.972.3 + '@aws-sdk/credential-provider-process': 3.972.3 + '@aws-sdk/credential-provider-sso': 3.972.3 + '@aws-sdk/credential-provider-web-identity': 3.972.3 + '@aws-sdk/nested-clients': 3.980.0 + '@aws-sdk/types': 3.973.1 + '@smithy/credential-provider-imds': 4.2.8 + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-login@3.972.3': + dependencies: + '@aws-sdk/core': 3.973.5 + '@aws-sdk/nested-clients': 3.980.0 + '@aws-sdk/types': 3.973.1 + '@smithy/property-provider': 4.2.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-node@3.972.4': + dependencies: + '@aws-sdk/credential-provider-env': 3.972.3 + '@aws-sdk/credential-provider-http': 3.972.5 + '@aws-sdk/credential-provider-ini': 3.972.3 + '@aws-sdk/credential-provider-process': 3.972.3 + '@aws-sdk/credential-provider-sso': 3.972.3 + '@aws-sdk/credential-provider-web-identity': 3.972.3 + '@aws-sdk/types': 3.973.1 + '@smithy/credential-provider-imds': 4.2.8 + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-process@3.972.3': + dependencies: + '@aws-sdk/core': 3.973.5 + '@aws-sdk/types': 3.973.1 + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-sso@3.972.3': + dependencies: + '@aws-sdk/client-sso': 3.980.0 + '@aws-sdk/core': 3.973.5 + '@aws-sdk/token-providers': 3.980.0 + '@aws-sdk/types': 3.973.1 + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-web-identity@3.972.3': + dependencies: + '@aws-sdk/core': 3.973.5 + '@aws-sdk/nested-clients': 3.980.0 + '@aws-sdk/types': 3.973.1 + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/middleware-bucket-endpoint@3.972.3': + dependencies: + '@aws-sdk/types': 3.973.1 + '@aws-sdk/util-arn-parser': 3.972.2 + '@smithy/node-config-provider': 4.3.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + '@smithy/util-config-provider': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-expect-continue@3.972.3': + dependencies: + '@aws-sdk/types': 3.973.1 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-flexible-checksums@3.972.3': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@aws-crypto/crc32c': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/core': 3.973.5 + '@aws-sdk/crc64-nvme': 3.972.0 + '@aws-sdk/types': 3.973.1 + '@smithy/is-array-buffer': 4.2.0 + '@smithy/node-config-provider': 4.3.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-stream': 4.5.11 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-host-header@3.972.3': + dependencies: + '@aws-sdk/types': 3.973.1 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-location-constraint@3.972.3': + dependencies: + '@aws-sdk/types': 3.973.1 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-logger@3.972.3': + dependencies: + '@aws-sdk/types': 3.973.1 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-recursion-detection@3.972.3': + dependencies: + '@aws-sdk/types': 3.973.1 + '@aws/lambda-invoke-store': 0.2.3 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-sdk-s3@3.972.5': + dependencies: + '@aws-sdk/core': 3.973.5 + '@aws-sdk/types': 3.973.1 + '@aws-sdk/util-arn-parser': 3.972.2 + '@smithy/core': 3.22.1 + '@smithy/node-config-provider': 4.3.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/signature-v4': 5.3.8 + '@smithy/smithy-client': 4.11.2 + '@smithy/types': 4.12.0 + '@smithy/util-config-provider': 4.2.0 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-stream': 4.5.11 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-ssec@3.972.3': + dependencies: + '@aws-sdk/types': 3.973.1 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-user-agent@3.972.5': + dependencies: + '@aws-sdk/core': 3.973.5 + '@aws-sdk/types': 3.973.1 + '@aws-sdk/util-endpoints': 3.980.0 + '@smithy/core': 3.22.1 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/nested-clients@3.980.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.973.5 + '@aws-sdk/middleware-host-header': 3.972.3 + '@aws-sdk/middleware-logger': 3.972.3 + '@aws-sdk/middleware-recursion-detection': 3.972.3 + '@aws-sdk/middleware-user-agent': 3.972.5 + '@aws-sdk/region-config-resolver': 3.972.3 + '@aws-sdk/types': 3.973.1 + '@aws-sdk/util-endpoints': 3.980.0 + '@aws-sdk/util-user-agent-browser': 3.972.3 + '@aws-sdk/util-user-agent-node': 3.972.3 + '@smithy/config-resolver': 4.4.6 + '@smithy/core': 3.22.1 + '@smithy/fetch-http-handler': 5.3.9 + '@smithy/hash-node': 4.2.8 + '@smithy/invalid-dependency': 4.2.8 + '@smithy/middleware-content-length': 4.2.8 + '@smithy/middleware-endpoint': 4.4.13 + '@smithy/middleware-retry': 4.4.30 + '@smithy/middleware-serde': 4.2.9 + '@smithy/middleware-stack': 4.2.8 + '@smithy/node-config-provider': 4.3.8 + '@smithy/node-http-handler': 4.4.9 + '@smithy/protocol-http': 5.3.8 + '@smithy/smithy-client': 4.11.2 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-body-length-node': 4.2.1 + '@smithy/util-defaults-mode-browser': 4.3.29 + '@smithy/util-defaults-mode-node': 4.2.32 + '@smithy/util-endpoints': 3.2.8 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-retry': 4.2.8 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/region-config-resolver@3.972.3': + dependencies: + '@aws-sdk/types': 3.973.1 + '@smithy/config-resolver': 4.4.6 + '@smithy/node-config-provider': 4.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/signature-v4-multi-region@3.981.0': + dependencies: + '@aws-sdk/middleware-sdk-s3': 3.972.5 + '@aws-sdk/types': 3.973.1 + '@smithy/protocol-http': 5.3.8 + '@smithy/signature-v4': 5.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/token-providers@3.980.0': + dependencies: + '@aws-sdk/core': 3.973.5 + '@aws-sdk/nested-clients': 3.980.0 + '@aws-sdk/types': 3.973.1 + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/types@3.973.1': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/util-arn-parser@3.972.2': + dependencies: + tslib: 2.8.1 + + '@aws-sdk/util-endpoints@3.980.0': + dependencies: + '@aws-sdk/types': 3.973.1 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + '@smithy/util-endpoints': 3.2.8 + tslib: 2.8.1 + + '@aws-sdk/util-endpoints@3.981.0': + dependencies: + '@aws-sdk/types': 3.973.1 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + '@smithy/util-endpoints': 3.2.8 + tslib: 2.8.1 + + '@aws-sdk/util-locate-window@3.965.4': + dependencies: + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-browser@3.972.3': + dependencies: + '@aws-sdk/types': 3.973.1 + '@smithy/types': 4.12.0 + bowser: 2.13.1 + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-node@3.972.3': + dependencies: + '@aws-sdk/middleware-user-agent': 3.972.5 + '@aws-sdk/types': 3.973.1 + '@smithy/node-config-provider': 4.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@aws-sdk/xml-builder@3.972.3': + dependencies: + '@smithy/types': 4.12.0 + fast-xml-parser: 5.3.4 + tslib: 2.8.1 + + '@aws/lambda-invoke-store@0.2.3': {} + '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.28.5 @@ -5056,6 +5960,344 @@ snapshots: '@rspack/lite-tapable@1.0.1': {} + '@smithy/abort-controller@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/chunked-blob-reader-native@4.2.1': + dependencies: + '@smithy/util-base64': 4.3.0 + tslib: 2.8.1 + + '@smithy/chunked-blob-reader@5.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/config-resolver@4.4.6': + dependencies: + '@smithy/node-config-provider': 4.3.8 + '@smithy/types': 4.12.0 + '@smithy/util-config-provider': 4.2.0 + '@smithy/util-endpoints': 3.2.8 + '@smithy/util-middleware': 4.2.8 + tslib: 2.8.1 + + '@smithy/core@3.22.1': + dependencies: + '@smithy/middleware-serde': 4.2.9 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-stream': 4.5.11 + '@smithy/util-utf8': 4.2.0 + '@smithy/uuid': 1.1.0 + tslib: 2.8.1 + + '@smithy/credential-provider-imds@4.2.8': + dependencies: + '@smithy/node-config-provider': 4.3.8 + '@smithy/property-provider': 4.2.8 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + tslib: 2.8.1 + + '@smithy/eventstream-codec@4.2.8': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@smithy/types': 4.12.0 + '@smithy/util-hex-encoding': 4.2.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-browser@4.2.8': + dependencies: + '@smithy/eventstream-serde-universal': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-config-resolver@4.3.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-node@4.2.8': + dependencies: + '@smithy/eventstream-serde-universal': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-universal@4.2.8': + dependencies: + '@smithy/eventstream-codec': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/fetch-http-handler@5.3.9': + dependencies: + '@smithy/protocol-http': 5.3.8 + '@smithy/querystring-builder': 4.2.8 + '@smithy/types': 4.12.0 + '@smithy/util-base64': 4.3.0 + tslib: 2.8.1 + + '@smithy/hash-blob-browser@4.2.9': + dependencies: + '@smithy/chunked-blob-reader': 5.2.0 + '@smithy/chunked-blob-reader-native': 4.2.1 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/hash-node@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + '@smithy/util-buffer-from': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/hash-stream-node@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/invalid-dependency@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/is-array-buffer@2.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/is-array-buffer@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/md5-js@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/middleware-content-length@4.2.8': + dependencies: + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/middleware-endpoint@4.4.13': + dependencies: + '@smithy/core': 3.22.1 + '@smithy/middleware-serde': 4.2.9 + '@smithy/node-config-provider': 4.3.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + '@smithy/url-parser': 4.2.8 + '@smithy/util-middleware': 4.2.8 + tslib: 2.8.1 + + '@smithy/middleware-retry@4.4.30': + dependencies: + '@smithy/node-config-provider': 4.3.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/service-error-classification': 4.2.8 + '@smithy/smithy-client': 4.11.2 + '@smithy/types': 4.12.0 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-retry': 4.2.8 + '@smithy/uuid': 1.1.0 + tslib: 2.8.1 + + '@smithy/middleware-serde@4.2.9': + dependencies: + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/middleware-stack@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/node-config-provider@4.3.8': + dependencies: + '@smithy/property-provider': 4.2.8 + '@smithy/shared-ini-file-loader': 4.4.3 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/node-http-handler@4.4.9': + dependencies: + '@smithy/abort-controller': 4.2.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/querystring-builder': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/property-provider@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/protocol-http@5.3.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/querystring-builder@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + '@smithy/util-uri-escape': 4.2.0 + tslib: 2.8.1 + + '@smithy/querystring-parser@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/service-error-classification@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + + '@smithy/shared-ini-file-loader@4.4.3': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/signature-v4@5.3.8': + dependencies: + '@smithy/is-array-buffer': 4.2.0 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + '@smithy/util-hex-encoding': 4.2.0 + '@smithy/util-middleware': 4.2.8 + '@smithy/util-uri-escape': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/smithy-client@4.11.2': + dependencies: + '@smithy/core': 3.22.1 + '@smithy/middleware-endpoint': 4.4.13 + '@smithy/middleware-stack': 4.2.8 + '@smithy/protocol-http': 5.3.8 + '@smithy/types': 4.12.0 + '@smithy/util-stream': 4.5.11 + tslib: 2.8.1 + + '@smithy/types@4.12.0': + dependencies: + tslib: 2.8.1 + + '@smithy/url-parser@4.2.8': + dependencies: + '@smithy/querystring-parser': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/util-base64@4.3.0': + dependencies: + '@smithy/util-buffer-from': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/util-body-length-browser@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-body-length-node@4.2.1': + dependencies: + tslib: 2.8.1 + + '@smithy/util-buffer-from@2.2.0': + dependencies: + '@smithy/is-array-buffer': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-buffer-from@4.2.0': + dependencies: + '@smithy/is-array-buffer': 4.2.0 + tslib: 2.8.1 + + '@smithy/util-config-provider@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-defaults-mode-browser@4.3.29': + dependencies: + '@smithy/property-provider': 4.2.8 + '@smithy/smithy-client': 4.11.2 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/util-defaults-mode-node@4.2.32': + dependencies: + '@smithy/config-resolver': 4.4.6 + '@smithy/credential-provider-imds': 4.2.8 + '@smithy/node-config-provider': 4.3.8 + '@smithy/property-provider': 4.2.8 + '@smithy/smithy-client': 4.11.2 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/util-endpoints@3.2.8': + dependencies: + '@smithy/node-config-provider': 4.3.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/util-hex-encoding@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-middleware@4.2.8': + dependencies: + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/util-retry@4.2.8': + dependencies: + '@smithy/service-error-classification': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/util-stream@4.5.11': + dependencies: + '@smithy/fetch-http-handler': 5.3.9 + '@smithy/node-http-handler': 4.4.9 + '@smithy/types': 4.12.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-buffer-from': 4.2.0 + '@smithy/util-hex-encoding': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/util-uri-escape@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-utf8@2.3.0': + dependencies: + '@smithy/util-buffer-from': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-utf8@4.2.0': + dependencies: + '@smithy/util-buffer-from': 4.2.0 + tslib: 2.8.1 + + '@smithy/util-waiter@4.2.8': + dependencies: + '@smithy/abort-controller': 4.2.8 + '@smithy/types': 4.12.0 + tslib: 2.8.1 + + '@smithy/uuid@1.1.0': + dependencies: + tslib: 2.8.1 + '@swc/helpers@0.5.17': dependencies: tslib: 2.8.1 @@ -5888,6 +7130,8 @@ snapshots: fast-deep-equal: 3.1.3 multicast-dns: 7.2.5 + bowser@2.13.1: {} + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 @@ -6649,6 +7893,10 @@ snapshots: dependencies: strnum: 1.1.2 + fast-xml-parser@5.3.4: + dependencies: + strnum: 2.1.2 + fastq@1.17.1: dependencies: reusify: 1.0.4 @@ -8260,6 +9508,8 @@ snapshots: strnum@1.1.2: {} + strnum@2.1.2: {} + supports-color@7.2.0: dependencies: has-flag: 4.0.0 diff --git a/src/locales/ach-UG/translation.json b/src/locales/ach-UG/translation.json index 25b2dbed3..476b452f2 100644 --- a/src/locales/ach-UG/translation.json +++ b/src/locales/ach-UG/translation.json @@ -373,6 +373,11 @@ "url": "crwdns8544:0crwdne8544:0", "username": "crwdns8546:0crwdne8546:0", "password": "crwdns8548:0crwdne8548:0", + "s3_bucket_name": "Bucket Name", + "s3_region": "Region", + "s3_access_key_id": "Access Key ID", + "s3_secret_access_key": "Secret Access Key", + "s3_custom_endpoint": "Custom Endpoint (Optional)", "skip": "crwdns8550:0crwdne8550:0", "next": "crwdns8552:0crwdne8552:0", "next_with_progress": "crwdns8920:0{step}crwdnd8920:0{steps}crwdne8920:0", diff --git a/src/locales/de-DE/translation.json b/src/locales/de-DE/translation.json index d18264195..6f0610f6d 100644 --- a/src/locales/de-DE/translation.json +++ b/src/locales/de-DE/translation.json @@ -382,6 +382,11 @@ "url": "URL", "username": "Benutzername", "password": "Passwort", + "s3_bucket_name": "Bucket-Name", + "s3_region": "Region", + "s3_access_key_id": "Zugriffs-Schlüssel-ID", + "s3_secret_access_key": "Geheimer Zugriffsschlüssel", + "s3_custom_endpoint": "Benutzerdefinierter Endpunkt (optional)", "skip": "Überspringen", "next": "Weiter", "next_with_progress": "Nächster Schritt (Schritt {step} von {steps})", diff --git a/src/locales/en-US/translation.json b/src/locales/en-US/translation.json index a5df027f6..1035e511c 100644 --- a/src/locales/en-US/translation.json +++ b/src/locales/en-US/translation.json @@ -382,6 +382,11 @@ "url": "URL", "username": "Username", "password": "Password", + "s3_bucket_name": "Bucket Name", + "s3_region": "Region", + "s3_access_key_id": "Access Key ID", + "s3_secret_access_key": "Secret Access Key", + "s3_custom_endpoint": "Custom Endpoint (Optional)", "skip": "Skip", "next": "Next", "next_with_progress": "Next (Step {step} of {steps})", diff --git a/src/locales/ja-JP/translation.json b/src/locales/ja-JP/translation.json index 1b7a04b01..2ebfd7262 100644 --- a/src/locales/ja-JP/translation.json +++ b/src/locales/ja-JP/translation.json @@ -382,6 +382,11 @@ "url": "URL", "username": "ユーザー名", "password": "パスワード", + "s3_bucket_name": "バケット名", + "s3_region": "リージョン", + "s3_access_key_id": "アクセスキーID", + "s3_secret_access_key": "シークレットアクセスキー", + "s3_custom_endpoint": "カスタムエンドポイント(オプション)", "skip": "スキップ", "next": "次へ", "next_with_progress": "次へ(ステップ{step}の全{steps}ステップ中)", diff --git a/src/locales/ru-RU/translation.json b/src/locales/ru-RU/translation.json index b41776979..6720d5173 100644 --- a/src/locales/ru-RU/translation.json +++ b/src/locales/ru-RU/translation.json @@ -382,6 +382,11 @@ "url": "URL", "username": "Имя пользователя", "password": "Пароль", + "s3_bucket_name": "Имя корзины", + "s3_region": "Регион", + "s3_access_key_id": "Идентификатор ключа доступа", + "s3_secret_access_key": "Секретный ключ доступа", + "s3_custom_endpoint": "Пользовательская конечная точка (необязательно)", "skip": "Пропустить", "next": "Далее", "next_with_progress": "Следующий шаг (шаг {step} из {steps})", diff --git a/src/locales/vi-VN/translation.json b/src/locales/vi-VN/translation.json index 9b35e23ec..6c10e5274 100644 --- a/src/locales/vi-VN/translation.json +++ b/src/locales/vi-VN/translation.json @@ -382,6 +382,11 @@ "url": "Url", "username": "Tên người dùng", "password": "Mật khẩu", + "s3_bucket_name": "Tên Bucket", + "s3_region": "Vùng", + "s3_access_key_id": "ID Khóa Truy Cập", + "s3_secret_access_key": "Khóa Truy Cập Bí Mật", + "s3_custom_endpoint": "Điểm Cuối Tùy Chỉnh (Tùy Chọn)", "skip": "Bỏ qua", "next": "Tiếp theo", "next_with_progress": "Tiếp theo (bước {step} trên {steps})", diff --git a/src/locales/zh-CN/translation.json b/src/locales/zh-CN/translation.json index 2409e2e52..6d78cd5dd 100644 --- a/src/locales/zh-CN/translation.json +++ b/src/locales/zh-CN/translation.json @@ -382,6 +382,11 @@ "url": "URL", "username": "用户名", "password": "密码", + "s3_bucket_name": "存储桶名称", + "s3_region": "区域", + "s3_access_key_id": "访问密钥 ID", + "s3_secret_access_key": "访问密钥密文", + "s3_custom_endpoint": "自定义端点(可选)", "skip": "跳过", "next": "下一步", "next_with_progress": "下一步(第 {step} 步 / 共 {steps} 步)", diff --git a/src/locales/zh-TW/translation.json b/src/locales/zh-TW/translation.json index fa6b99483..a9b98bd0d 100644 --- a/src/locales/zh-TW/translation.json +++ b/src/locales/zh-TW/translation.json @@ -382,6 +382,11 @@ "url": "網址", "username": "使用者名稱", "password": "密碼", + "s3_bucket_name": "儲存貯體名稱", + "s3_region": "區域", + "s3_access_key_id": "存取金鑰 ID", + "s3_secret_access_key": "私密存取金鑰", + "s3_custom_endpoint": "自訂端點(選用)", "skip": "跳過", "next": "下一步", "next_with_progress": "下一步(第 {step} 步 / 共 {steps} 步)", diff --git a/src/pages/components/FileSystemParams/index.tsx b/src/pages/components/FileSystemParams/index.tsx index f05dd5e28..8e7549985 100644 --- a/src/pages/components/FileSystemParams/index.tsx +++ b/src/pages/components/FileSystemParams/index.tsx @@ -47,6 +47,10 @@ const FileSystemParams: React.FC<{ key: "dropbox", name: "Dropbox", }, + { + key: "s3", + name: "Amazon S3", + }, ]; const netDiskType = netDiskTypeMap[fileSystemType]; From ba73e4a9fbed06afc1b152f14ad345ca5b3b39ab Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Tue, 3 Feb 2026 16:20:48 +0900 Subject: [PATCH 02/15] fix --- packages/filesystem/s3/rw.ts | 44 ++++++++++++++++++------------------ packages/filesystem/s3/s3.ts | 14 +++++++++--- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/packages/filesystem/s3/rw.ts b/packages/filesystem/s3/rw.ts index b7e8fe198..acd310d3d 100644 --- a/packages/filesystem/s3/rw.ts +++ b/packages/filesystem/s3/rw.ts @@ -25,7 +25,7 @@ export class S3FileReader implements FileReader { * @returns File content as string or Blob * @throws {Error} If file not found or read fails */ - async read(type?: "string" | "blob"): Promise { + async read(type: "string" | "blob" = "blob"): Promise { try { const command = new GetObjectCommand({ Bucket: this.bucket, @@ -40,28 +40,27 @@ export class S3FileReader implements FileReader { // Convert the stream to the requested format const chunks: Uint8Array[] = []; - const reader = response.Body.transformToWebStream().getReader(); - - while (true) { - const { done, value } = await reader.read(); - if (done) break; - chunks.push(value); - } - - const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0); - const result = new Uint8Array(totalLength); - let offset = 0; - for (const chunk of chunks) { - result.set(chunk, offset); - offset += chunk.length; + const stream = response.Body.transformToWebStream(); + + if (type === "string") { + // Streaming decode to string (省内存) + const reader = stream.getReader(); + const decoder = new TextDecoder(); + let result = ""; + while (true) { + const { done, value } = await reader.read(); + if (done) break; + result += decoder.decode(value, { stream: true }); + } + // 最后 flush + result += decoder.decode(); + return result; + + } else { + // 返回 Blob,避免 JS 层缓冲与拼接,走底层最优路径 + return new Response(stream).blob(); } - switch (type) { - case "string": - return new TextDecoder().decode(result); - default: - return new Blob([result]); - } } catch (error: any) { if (error.name === "NoSuchKey") { throw new Error(`File not found: ${this.key}`); @@ -101,7 +100,8 @@ export class S3FileWriter implements FileWriter { const metadata: Record = {}; if (this.modifiedDate) { - metadata.createtime = this.modifiedDate.toString(); + // 用 ISO 8601 格式 + metadata.createtime = new Date(this.modifiedDate).toISOString(); // 规范格式 } const command = new PutObjectCommand({ diff --git a/packages/filesystem/s3/s3.ts b/packages/filesystem/s3/s3.ts index 8f5310135..c98a9e840 100644 --- a/packages/filesystem/s3/s3.ts +++ b/packages/filesystem/s3/s3.ts @@ -40,7 +40,8 @@ export default class S3FileSystem implements FileSystem { accessKeyId: string, secretAccessKey: string, endpoint?: string, - basePath?: string + basePath?: string, + usePathStyle: boolean = true // 默认兼容S3 ) { this.bucket = bucket; this.region = region; @@ -52,11 +53,14 @@ export default class S3FileSystem implements FileSystem { accessKeyId, secretAccessKey, }, - forcePathStyle: true, + // forcePathStyle: true 对 AWS 官方 S3 不是最佳实践(会用 path-style URL,已被逐渐弃用),对 MinIO 等兼容服务则是必须的。硬编码会导致部分用户配置失败。 + forcePathStyle: usePathStyle, }; if (endpoint) { config.endpoint = endpoint; + // 自动检测:如果 endpoint 包含 amazonaws.com,设为 false。 + if (endpoint.includes("amazonaws.com")) config.forcePathStyle = false; } this.client = new S3Client(config); @@ -108,7 +112,7 @@ export default class S3FileSystem implements FileSystem { */ async openDir(path: string): Promise { const newBasePath = joinPath(this.basePath, path); - return new S3FileSystem( + const fs = new S3FileSystem( this.bucket, this.region, "", // These won't be used since we're reusing the client @@ -116,6 +120,10 @@ export default class S3FileSystem implements FileSystem { undefined, newBasePath ); + // openDir 又 new 一个 S3FileSystem,但传了空字符串的 AK/SK,导致逻辑不清晰。 + // 复用原有 client,只修改 basePath。 + fs.client = this.client; // 复用 client + return fs; } /** From 66194284a9c6a078207e3a35c7b920f5ad682619 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Tue, 3 Feb 2026 16:24:23 +0900 Subject: [PATCH 03/15] fix --- packages/filesystem/s3/rw.ts | 5 +---- packages/filesystem/s3/s3.ts | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/filesystem/s3/rw.ts b/packages/filesystem/s3/rw.ts index acd310d3d..409f7f965 100644 --- a/packages/filesystem/s3/rw.ts +++ b/packages/filesystem/s3/rw.ts @@ -39,7 +39,6 @@ export class S3FileReader implements FileReader { } // Convert the stream to the requested format - const chunks: Uint8Array[] = []; const stream = response.Body.transformToWebStream(); if (type === "string") { @@ -55,12 +54,10 @@ export class S3FileReader implements FileReader { // 最后 flush result += decoder.decode(); return result; - } else { // 返回 Blob,避免 JS 层缓冲与拼接,走底层最优路径 return new Response(stream).blob(); } - } catch (error: any) { if (error.name === "NoSuchKey") { throw new Error(`File not found: ${this.key}`); @@ -101,7 +98,7 @@ export class S3FileWriter implements FileWriter { const metadata: Record = {}; if (this.modifiedDate) { // 用 ISO 8601 格式 - metadata.createtime = new Date(this.modifiedDate).toISOString(); // 规范格式 + metadata.createtime = new Date(this.modifiedDate).toISOString(); // 规范格式 } const command = new PutObjectCommand({ diff --git a/packages/filesystem/s3/s3.ts b/packages/filesystem/s3/s3.ts index c98a9e840..4708f96e0 100644 --- a/packages/filesystem/s3/s3.ts +++ b/packages/filesystem/s3/s3.ts @@ -41,7 +41,7 @@ export default class S3FileSystem implements FileSystem { secretAccessKey: string, endpoint?: string, basePath?: string, - usePathStyle: boolean = true // 默认兼容S3 + usePathStyle: boolean = true // 默认兼容S3 ) { this.bucket = bucket; this.region = region; From 3a4e4fa3a566bacd7cade7367b779effd4160a41 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Tue, 3 Feb 2026 16:41:00 +0900 Subject: [PATCH 04/15] fix 02 --- packages/filesystem/s3/s3.ts | 58 ++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/packages/filesystem/s3/s3.ts b/packages/filesystem/s3/s3.ts index 4708f96e0..8cc487511 100644 --- a/packages/filesystem/s3/s3.ts +++ b/packages/filesystem/s3/s3.ts @@ -58,6 +58,12 @@ export default class S3FileSystem implements FileSystem { }; if (endpoint) { + // AWS SDK v3 要求 endpoint 是完整 URL(带 https://)。缺少协议会导致 InvalidEndpoint 或连接失败。 + // 自动补全协议(常见兼容做法) + let fixedEndpoint = `${endpoint}`.trim(); + if (!fixedEndpoint.startsWith("http://") && !fixedEndpoint.startsWith("https://")) { + fixedEndpoint = `https://${fixedEndpoint}`; + } config.endpoint = endpoint; // 自动检测:如果 endpoint 包含 amazonaws.com,设为 false。 if (endpoint.includes("amazonaws.com")) config.forcePathStyle = false; @@ -78,18 +84,27 @@ export default class S3FileSystem implements FileSystem { }); await this.client.send(command); } catch (error: any) { + if (error.name === "NotFound") { + throw new Error("NotFound"); // Bucket 不存在 + } if ( error.name === "InvalidAccessKeyId" || error.name === "SignatureDoesNotMatch" || error.name === "InvalidClientTokenId" ) { - throw new WarpTokenError(error); + throw new WarpTokenError(error); // AccessKey 或 SecretKey 无效 + } + if (error.name === "AccessDenied") { + throw new Error("Access Denied"); // 无权限访问该 Bucket(Access Denied) + } + if (error.name === "PermanentRedirect") { + throw new Error("Access Denied"); // Region 设置错误,请检查 region 是否匹配 Bucket 所在区域 } if (error.name === "NoSuchBucket") { throw new Error(`Bucket not found: ${this.bucket}`); } if (error.message?.includes("getaddrinfo") || error.message?.includes("fetch failed")) { - throw new Error("Network connection failed. Please check your internet connection."); + throw new Error("Network connection failed. Please check your internet connection."); // 网络连接失败,请检查 endpoint 或网络 } throw error; } @@ -115,10 +130,11 @@ export default class S3FileSystem implements FileSystem { const fs = new S3FileSystem( this.bucket, this.region, - "", // These won't be used since we're reusing the client + "", // 占位: These won't be used since we're reusing the client "", undefined, - newBasePath + newBasePath, + true // forcePathStyle 同父 ); // openDir 又 new 一个 S3FileSystem,但传了空字符串的 AK/SK,导致逻辑不清晰。 // 复用原有 client,只修改 basePath。 @@ -187,25 +203,37 @@ export default class S3FileSystem implements FileSystem { Prefix: prefix, Delimiter: "/", ContinuationToken: continuationToken, + MaxKeys: 1000, // ← 每次最多 1000,防滥用 }); const response = await this.client.send(command); + // 处理 CommonPrefixes(子目录) + // if (response.CommonPrefixes) { + // for (const prefix of response.CommonPrefixes) { + // if (prefix.Prefix && prefix.Prefix !== this.basePath) { + // } + // } + // } + + // 处理 Contents(文件) if (response.Contents) { - for (const object of response.Contents) { - if (!object.Key) continue; + for (const obj of response.Contents) { + if (!obj.Key) continue; + if (obj.Key && obj.Key.endsWith("/")) continue; // 跳过目录占位符 + if (obj.Key === this.basePath.slice(1)) continue; // 跳过 prefix 本身 - // Skip the directory marker itself - if (object.Key === prefix || object.Key.endsWith("/")) continue; + // const name = obj.Key.substring(prefix.length); + const relativeKey = obj.Key.slice(this.basePath.length); + if (!relativeKey) continue; - const name = object.Key.substring(prefix.length); - const lastModified = object.LastModified?.getTime() || Date.now(); + const lastModified = obj.LastModified?.getTime() || Date.now(); files.push({ - name, + name: relativeKey, path: this.basePath, - size: object.Size || 0, - digest: object.ETag?.replace(/"/g, "") || "", + size: obj.Size || 0, + digest: obj.ETag?.replace(/"/g, "") || "", createtime: lastModified, updatetime: lastModified, }); @@ -215,6 +243,10 @@ export default class S3FileSystem implements FileSystem { continuationToken = response.NextContinuationToken; } while (continuationToken); + if (files.length > 10000) { + console.warn(`Directory listing truncated: >10000 items under ${this.basePath}`); + } + return files; } catch (error: any) { if (error.name === "AccessDenied") { From 1f82929c4f817d99db63d136022daec84bbc4d03 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Tue, 3 Feb 2026 16:42:30 +0900 Subject: [PATCH 05/15] lint --- packages/filesystem/s3/s3.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/filesystem/s3/s3.ts b/packages/filesystem/s3/s3.ts index 8cc487511..4431dd999 100644 --- a/packages/filesystem/s3/s3.ts +++ b/packages/filesystem/s3/s3.ts @@ -203,7 +203,7 @@ export default class S3FileSystem implements FileSystem { Prefix: prefix, Delimiter: "/", ContinuationToken: continuationToken, - MaxKeys: 1000, // ← 每次最多 1000,防滥用 + MaxKeys: 1000, // ← 每次最多 1000,防滥用 }); const response = await this.client.send(command); From 0815b9dce9f2c0f33b75266e805b3a96df89f5bc Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Tue, 3 Feb 2026 16:56:11 +0900 Subject: [PATCH 06/15] =?UTF-8?q?PutObjectCommand=20=E7=9A=84=20Body=20?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E7=9B=B4=E6=8E=A5=E5=86=99=E5=85=A5=20Blob?= =?UTF-8?q?=20content?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/filesystem/s3/rw.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/filesystem/s3/rw.ts b/packages/filesystem/s3/rw.ts index 409f7f965..d71409078 100644 --- a/packages/filesystem/s3/rw.ts +++ b/packages/filesystem/s3/rw.ts @@ -93,7 +93,6 @@ export class S3FileWriter implements FileWriter { * @throws {Error} If upload fails */ async write(content: string | Blob): Promise { - const body = content instanceof Blob ? new Uint8Array(await content.arrayBuffer()) : content; const metadata: Record = {}; if (this.modifiedDate) { @@ -104,7 +103,7 @@ export class S3FileWriter implements FileWriter { const command = new PutObjectCommand({ Bucket: this.bucket, Key: this.key, - Body: body, + Body: content, Metadata: Object.keys(metadata).length > 0 ? metadata : undefined, }); From f9233388a56e186fe336a8475186da3ceff5031d Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Tue, 3 Feb 2026 17:06:42 +0900 Subject: [PATCH 07/15] added comment --- packages/filesystem/s3/rw.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/filesystem/s3/rw.ts b/packages/filesystem/s3/rw.ts index d71409078..f4526fd4e 100644 --- a/packages/filesystem/s3/rw.ts +++ b/packages/filesystem/s3/rw.ts @@ -103,7 +103,7 @@ export class S3FileWriter implements FileWriter { const command = new PutObjectCommand({ Bucket: this.bucket, Key: this.key, - Body: content, + Body: content, // API 的 Body 接受 string | Blob | Uint8Array | Buffer | Readable | ReadableStream Metadata: Object.keys(metadata).length > 0 ? metadata : undefined, }); From 65361891ed27d66bb496476409c1f48785d25257 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Tue, 3 Feb 2026 17:15:20 +0900 Subject: [PATCH 08/15] lint --- packages/filesystem/s3/rw.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/filesystem/s3/rw.ts b/packages/filesystem/s3/rw.ts index f4526fd4e..008d0bb8d 100644 --- a/packages/filesystem/s3/rw.ts +++ b/packages/filesystem/s3/rw.ts @@ -93,7 +93,6 @@ export class S3FileWriter implements FileWriter { * @throws {Error} If upload fails */ async write(content: string | Blob): Promise { - const metadata: Record = {}; if (this.modifiedDate) { // 用 ISO 8601 格式 From aa975d61440505cfbee438541d5a59f6ab70ea2b Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Fri, 13 Feb 2026 19:04:25 +0900 Subject: [PATCH 09/15] implementation fix --- packages/filesystem/s3/rw.ts | 24 +++++++----------------- packages/filesystem/s3/s3.ts | 2 +- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/packages/filesystem/s3/rw.ts b/packages/filesystem/s3/rw.ts index 008d0bb8d..f6e95689b 100644 --- a/packages/filesystem/s3/rw.ts +++ b/packages/filesystem/s3/rw.ts @@ -38,25 +38,15 @@ export class S3FileReader implements FileReader { throw new Error("Empty response body from S3"); } - // Convert the stream to the requested format - const stream = response.Body.transformToWebStream(); - if (type === "string") { - // Streaming decode to string (省内存) - const reader = stream.getReader(); - const decoder = new TextDecoder(); - let result = ""; - while (true) { - const { done, value } = await reader.read(); - if (done) break; - result += decoder.decode(value, { stream: true }); - } - // 最后 flush - result += decoder.decode(); - return result; + // Built-in v3 helper + const text = await response.Body.transformToString(); + return text; } else { - // 返回 Blob,避免 JS 层缓冲与拼接,走底层最优路径 - return new Response(stream).blob(); + // Or transformToByteArray() + const stream = response.Body.transformToWebStream(); + const blob = await new Response(stream).blob(); + return blob; } } catch (error: any) { if (error.name === "NoSuchKey") { diff --git a/packages/filesystem/s3/s3.ts b/packages/filesystem/s3/s3.ts index 4431dd999..263a0ef5a 100644 --- a/packages/filesystem/s3/s3.ts +++ b/packages/filesystem/s3/s3.ts @@ -64,7 +64,7 @@ export default class S3FileSystem implements FileSystem { if (!fixedEndpoint.startsWith("http://") && !fixedEndpoint.startsWith("https://")) { fixedEndpoint = `https://${fixedEndpoint}`; } - config.endpoint = endpoint; + config.endpoint = fixedEndpoint; // 自动检测:如果 endpoint 包含 amazonaws.com,设为 false。 if (endpoint.includes("amazonaws.com")) config.forcePathStyle = false; } From d3e1343700cb82d7af78e3142c468b281bb16f42 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Fri, 13 Feb 2026 19:05:07 +0900 Subject: [PATCH 10/15] 3.981.0 -> 3.989.0 --- package.json | 2 +- pnpm-lock.yaml | 379 +++++++++++++++++++++++-------------------------- 2 files changed, 177 insertions(+), 204 deletions(-) diff --git a/package.json b/package.json index 251dd01aa..9c22d34ee 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ }, "dependencies": { "@arco-design/web-react": "^2.66.7", - "@aws-sdk/client-s3": "^3.981.0", + "@aws-sdk/client-s3": "^3.989.0", "@dnd-kit/core": "^6.3.1", "@dnd-kit/modifiers": "^9.0.0", "@dnd-kit/sortable": "^10.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1d2d31566..29b92fa70 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^2.66.7 version: 2.66.7(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@aws-sdk/client-s3': - specifier: ^3.981.0 - version: 3.981.0 + specifier: ^3.989.0 + version: 3.989.0 '@dnd-kit/core': specifier: ^6.3.1 version: 6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -264,52 +264,52 @@ packages: '@aws-crypto/util@5.2.0': resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} - '@aws-sdk/client-s3@3.981.0': - resolution: {integrity: sha512-zX3Xqm7V30J1D2II7WBL23SyqIIMD0wMzpiE+VosBxH6fAeXgrjIwSudCypNgnE1EK9OZoZMT3mJtkbUqUDdaA==} + '@aws-sdk/client-s3@3.989.0': + resolution: {integrity: sha512-ccz2miIetWAgrJYmKCpSnRjF8jew7DPstl54nufhfPMtM1MLxD2z55eSk1eJj3Umhu4CioNN1aY1ILT7fwlSiw==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-sso@3.980.0': - resolution: {integrity: sha512-AhNXQaJ46C1I+lQ+6Kj+L24il5K9lqqIanJd8lMszPmP7bLnmX0wTKK0dxywcvrLdij3zhWttjAKEBNgLtS8/A==} + '@aws-sdk/client-sso@3.989.0': + resolution: {integrity: sha512-3sC+J1ru5VFXLgt9KZmXto0M7mnV5RkS6FNGwRMK3XrojSjHso9DLOWjbnXhbNv4motH8vu53L1HK2VC1+Nj5w==} engines: {node: '>=20.0.0'} - '@aws-sdk/core@3.973.5': - resolution: {integrity: sha512-IMM7xGfLGW6lMvubsA4j6BHU5FPgGAxoQ/NA63KqNLMwTS+PeMBcx8DPHL12Vg6yqOZnqok9Mu4H2BdQyq7gSA==} + '@aws-sdk/core@3.973.9': + resolution: {integrity: sha512-cyUOfJSizn8da7XrBEFBf4UMI4A6JQNX6ZFcKtYmh/CrwfzsDcabv3k/z0bNwQ3pX5aeq5sg/8Bs/ASiL0bJaA==} engines: {node: '>=20.0.0'} '@aws-sdk/crc64-nvme@3.972.0': resolution: {integrity: sha512-ThlLhTqX68jvoIVv+pryOdb5coP1cX1/MaTbB9xkGDCbWbsqQcLqzPxuSoW1DCnAAIacmXCWpzUNOB9pv+xXQw==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-env@3.972.3': - resolution: {integrity: sha512-OBYNY4xQPq7Rx+oOhtyuyO0AQvdJSpXRg7JuPNBJH4a1XXIzJQl4UHQTPKZKwfJXmYLpv4+OkcFen4LYmDPd3g==} + '@aws-sdk/credential-provider-env@3.972.7': + resolution: {integrity: sha512-r8kBtglvLjGxBT87l6Lqkh9fL8yJJ6O4CYQPjKlj3AkCuL4/4784x3rxxXWw9LTKXOo114VB6mjxAuy5pI7XIg==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-http@3.972.5': - resolution: {integrity: sha512-GpvBgEmSZPvlDekd26Zi+XsI27Qz7y0utUx0g2fSTSiDzhnd1FSa1owuodxR0BcUKNL7U2cOVhhDxgZ4iSoPVg==} + '@aws-sdk/credential-provider-http@3.972.9': + resolution: {integrity: sha512-40caFblEg/TPrp9EpvyMxp4xlJ5TuTI+A8H6g8FhHn2hfH2PObFAPLF9d5AljK/G69E1YtTklkuQeAwPlV3w8Q==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-ini@3.972.3': - resolution: {integrity: sha512-rMQAIxstP7cLgYfsRGrGOlpyMl0l8JL2mcke3dsIPLWke05zKOFyR7yoJzWCsI/QiIxjRbxpvPiAeKEA6CoYkg==} + '@aws-sdk/credential-provider-ini@3.972.7': + resolution: {integrity: sha512-zeYKrMwM5bCkHFho/x3+1OL0vcZQ0OhTR7k35tLq74+GP5ieV3juHXTZfa2LVE0Bg75cHIIerpX0gomVOhzo/w==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-login@3.972.3': - resolution: {integrity: sha512-Gc3O91iVvA47kp2CLIXOwuo5ffo1cIpmmyIewcYjAcvurdFHQ8YdcBe1KHidnbbBO4/ZtywGBACsAX5vr3UdoA==} + '@aws-sdk/credential-provider-login@3.972.7': + resolution: {integrity: sha512-Q103cLU6OjAllYjX7+V+PKQw654jjvZUkD+lbUUiFbqut6gR5zwl1DrelvJPM5hnzIty7BCaxaRB3KMuz3M/ug==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-node@3.972.4': - resolution: {integrity: sha512-UwerdzosMSY7V5oIZm3NsMDZPv2aSVzSkZxYxIOWHBeKTZlUqW7XpHtJMZ4PZpJ+HMRhgP+MDGQx4THndgqJfQ==} + '@aws-sdk/credential-provider-node@3.972.8': + resolution: {integrity: sha512-AaDVOT7iNJyLjc3j91VlucPZ4J8Bw+eu9sllRDugJqhHWYyR3Iyp2huBUW8A3+DfHoh70sxGkY92cThAicSzlQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-process@3.972.3': - resolution: {integrity: sha512-xkSY7zjRqeVc6TXK2xr3z1bTLm0wD8cj3lAkproRGaO4Ku7dPlKy843YKnHrUOUzOnMezdZ4xtmFc0eKIDTo2w==} + '@aws-sdk/credential-provider-process@3.972.7': + resolution: {integrity: sha512-hxMo1V3ujWWrQSONxQJAElnjredkRpB6p8SDjnvRq70IwYY38R/CZSys0IbhRPxdgWZ5j12yDRk2OXhxw4Gj3g==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-sso@3.972.3': - resolution: {integrity: sha512-8Ww3F5Ngk8dZ6JPL/V5LhCU1BwMfQd3tLdoEuzaewX8FdnT633tPr+KTHySz9FK7fFPcz5qG3R5edVEhWQD4AA==} + '@aws-sdk/credential-provider-sso@3.972.7': + resolution: {integrity: sha512-ZGKBOHEj8Ap15jhG2XMncQmKLTqA++2DVU2eZfLu3T/pkwDyhCp5eZv5c/acFxbZcA/6mtxke+vzO/n+aeHs4A==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-web-identity@3.972.3': - resolution: {integrity: sha512-62VufdcH5rRfiRKZRcf1wVbbt/1jAntMj1+J0qAd+r5pQRg2t0/P9/Rz16B1o5/0Se9lVL506LRjrhIJAhYBfA==} + '@aws-sdk/credential-provider-web-identity@3.972.7': + resolution: {integrity: sha512-AbYupBIoSJoVMlbMqBhNvPhqj+CdGtzW7Uk4ZIMBm2br18pc3rkG1VaKVFV85H87QCvLHEnni1idJjaX1wOmIw==} engines: {node: '>=20.0.0'} '@aws-sdk/middleware-bucket-endpoint@3.972.3': @@ -320,8 +320,8 @@ packages: resolution: {integrity: sha512-4msC33RZsXQpUKR5QR4HnvBSNCPLGHmB55oDiROqqgyOc+TOfVu2xgi5goA7ms6MdZLeEh2905UfWMnMMF4mRg==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-flexible-checksums@3.972.3': - resolution: {integrity: sha512-MkNGJ6qB9kpsLwL18kC/ZXppsJbftHVGCisqpEVbTQsum8CLYDX1Bmp/IvhRGNxsqCO2w9/4PwhDKBjG3Uvr4Q==} + '@aws-sdk/middleware-flexible-checksums@3.972.7': + resolution: {integrity: sha512-YU/5rpz8k2mwFGi2M0px9ChOQZY7Bbow5knB2WLRVPqDM/cG8T5zj55UaWS1qcaFpE7vCX9a9/kvYBlKGcD+KA==} engines: {node: '>=20.0.0'} '@aws-sdk/middleware-host-header@3.972.3': @@ -340,32 +340,32 @@ packages: resolution: {integrity: sha512-PY57QhzNuXHnwbJgbWYTrqIDHYSeOlhfYERTAuc16LKZpTZRJUjzBFokp9hF7u1fuGeE3D70ERXzdbMBOqQz7Q==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-sdk-s3@3.972.5': - resolution: {integrity: sha512-3IgeIDiQ15tmMBFIdJ1cTy3A9rXHGo+b9p22V38vA3MozeMyVC8VmCYdDLA0iMWo4VHA9LDJTgCM0+xU3wjBOg==} + '@aws-sdk/middleware-sdk-s3@3.972.9': + resolution: {integrity: sha512-F4Ak2HM7te/o3izFTqg/jUTBLjavpaJ5iynKM6aLMwNddXbwAZQ1VbIG8RFUHBo7fBHj2eeN2FNLtIFT4ejWYQ==} engines: {node: '>=20.0.0'} '@aws-sdk/middleware-ssec@3.972.3': resolution: {integrity: sha512-dU6kDuULN3o3jEHcjm0c4zWJlY1zWVkjG9NPe9qxYLLpcbdj5kRYBS2DdWYD+1B9f910DezRuws7xDEqKkHQIg==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-user-agent@3.972.5': - resolution: {integrity: sha512-TVZQ6PWPwQbahUI8V+Er+gS41ctIawcI/uMNmQtQ7RMcg3JYn6gyKAFKUb3HFYx2OjYlx1u11sETSwwEUxVHTg==} + '@aws-sdk/middleware-user-agent@3.972.9': + resolution: {integrity: sha512-1g1B7yf7KzessB0mKNiV9gAHEwbM662xgU+VE4LxyGe6kVGZ8LqYsngjhE+Stna09CJ7Pxkjr6Uq1OtbGwJJJg==} engines: {node: '>=20.0.0'} - '@aws-sdk/nested-clients@3.980.0': - resolution: {integrity: sha512-/dONY5xc5/CCKzOqHZCTidtAR4lJXWkGefXvTRKdSKMGaYbbKsxDckisd6GfnvPSLxWtvQzwgRGRutMRoYUApQ==} + '@aws-sdk/nested-clients@3.989.0': + resolution: {integrity: sha512-Dbk2HMPU3mb6RrSRzgf0WCaWSbgtZG258maCpuN2/ONcAQNpOTw99V5fU5CA1qVK6Vkm4Fwj2cnOnw7wbGVlOw==} engines: {node: '>=20.0.0'} '@aws-sdk/region-config-resolver@3.972.3': resolution: {integrity: sha512-v4J8qYAWfOMcZ4MJUyatntOicTzEMaU7j3OpkRCGGFSL2NgXQ5VbxauIyORA+pxdKZ0qQG2tCQjQjZDlXEC3Ow==} engines: {node: '>=20.0.0'} - '@aws-sdk/signature-v4-multi-region@3.981.0': - resolution: {integrity: sha512-T/+h9df0DALAXXP+YfZ8bgmH6cEN7HAg6BqHe3t38GhHgQ1HULXwK5XMhiLWiHpytDdhLqiVH41SRgW8ynBl6Q==} + '@aws-sdk/signature-v4-multi-region@3.989.0': + resolution: {integrity: sha512-rVhR/BUZdnru7tLlxWD+uzoKB1LAs2L0pcoh6rYgIYuCtQflnsC6Ud0SpfqIsOapBSBKXdoW73IITFf+XFMdCQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/token-providers@3.980.0': - resolution: {integrity: sha512-1nFileg1wAgDmieRoj9dOawgr2hhlh7xdvcH57b1NnqfPaVlcqVJyPc6k3TLDUFPY69eEwNxdGue/0wIz58vjA==} + '@aws-sdk/token-providers@3.989.0': + resolution: {integrity: sha512-OdBByMv+OjOZoekrk4THPFpLuND5aIQbDHCGh3n2rvifAbm31+6e0OLhxSeCF1UMPm+nKq12bXYYEoCIx5SQBg==} engines: {node: '>=20.0.0'} '@aws-sdk/types@3.973.1': @@ -376,12 +376,8 @@ packages: resolution: {integrity: sha512-VkykWbqMjlSgBFDyrY3nOSqupMc6ivXuGmvci6Q3NnLq5kC+mKQe2QBZ4nrWRE/jqOxeFP2uYzLtwncYYcvQDg==} engines: {node: '>=20.0.0'} - '@aws-sdk/util-endpoints@3.980.0': - resolution: {integrity: sha512-AjKBNEc+rjOZQE1HwcD9aCELqg1GmUj1rtICKuY8cgwB73xJ4U/kNyqKKpN2k9emGqlfDY2D8itIp/vDc6OKpw==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/util-endpoints@3.981.0': - resolution: {integrity: sha512-a8nXh/H3/4j+sxhZk+N3acSDlgwTVSZbX9i55dx41gI1H+geuonuRG+Shv3GZsCb46vzc08RK2qC78ypO8uRlg==} + '@aws-sdk/util-endpoints@3.989.0': + resolution: {integrity: sha512-eKmAOeQM4Qusq0jtcbZPiNWky8XaojByKC/n+THbJ8vJf7t4ys8LlcZ4PrBSHZISe9cC484mQsPVOQh6iySjqw==} engines: {node: '>=20.0.0'} '@aws-sdk/util-locate-window@3.965.4': @@ -391,8 +387,8 @@ packages: '@aws-sdk/util-user-agent-browser@3.972.3': resolution: {integrity: sha512-JurOwkRUcXD/5MTDBcqdyQ9eVedtAsZgw5rBwktsPTN7QtPiS2Ld1jkJepNgYoCufz1Wcut9iup7GJDoIHp8Fw==} - '@aws-sdk/util-user-agent-node@3.972.3': - resolution: {integrity: sha512-gqG+02/lXQtO0j3US6EVnxtwwoXQC5l2qkhLCrqUrqdtcQxV7FDMbm9wLjKqoronSHyELGTjbFKK/xV5q1bZNA==} + '@aws-sdk/util-user-agent-node@3.972.7': + resolution: {integrity: sha512-oyhv+FjrgHjP+F16cmsrJzNP4qaRJzkV1n9Lvv4uyh3kLqo3rIe9NSBSBa35f2TedczfG2dD+kaQhHBB47D6Og==} engines: {node: '>=20.0.0'} peerDependencies: aws-crt: '>=1.0.0' @@ -400,8 +396,8 @@ packages: aws-crt: optional: true - '@aws-sdk/xml-builder@3.972.3': - resolution: {integrity: sha512-bCk63RsBNCWW4tt5atv5Sbrh+3J3e8YzgyF6aZb1JeXcdzG4k5SlPLeTMFOIXFuuFHIwgphUhn4i3uS/q49eww==} + '@aws-sdk/xml-builder@3.972.4': + resolution: {integrity: sha512-0zJ05ANfYqI6+rGqj8samZBFod0dPPousBjLEqg8WdxSgbMAkRgLyn81lP215Do0rFJ/17LIXwr7q0yK24mP6Q==} engines: {node: '>=20.0.0'} '@aws/lambda-invoke-store@0.2.3': @@ -1075,67 +1071,56 @@ packages: resolution: {integrity: sha512-+xmiDGGaSfIIOXMzkhJ++Oa0Gwvl9oXUeIiwarsdRXSe27HUIvjbSIpPxvnNsRebsNdUo7uAiQVgBD1hVriwSQ==} cpu: [arm] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.44.2': resolution: {integrity: sha512-bDHvhzOfORk3wt8yxIra8N4k/N0MnKInCW5OGZaeDYa/hMrdPaJzo7CSkjKZqX4JFUWjUGm88lI6QJLCM7lDrA==} cpu: [arm] os: [linux] - libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.44.2': resolution: {integrity: sha512-NMsDEsDiYghTbeZWEGnNi4F0hSbGnsuOG+VnNvxkKg0IGDvFh7UVpM/14mnMwxRxUf9AdAVJgHPvKXf6FpMB7A==} cpu: [arm64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.44.2': resolution: {integrity: sha512-lb5bxXnxXglVq+7imxykIp5xMq+idehfl+wOgiiix0191av84OqbjUED+PRC5OA8eFJYj5xAGcpAZ0pF2MnW+A==} cpu: [arm64] os: [linux] - libc: [musl] '@rollup/rollup-linux-loongarch64-gnu@4.44.2': resolution: {integrity: sha512-Yl5Rdpf9pIc4GW1PmkUGHdMtbx0fBLE1//SxDmuf3X0dUC57+zMepow2LK0V21661cjXdTn8hO2tXDdAWAqE5g==} cpu: [loong64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-powerpc64le-gnu@4.44.2': resolution: {integrity: sha512-03vUDH+w55s680YYryyr78jsO1RWU9ocRMaeV2vMniJJW/6HhoTBwyyiiTPVHNWLnhsnwcQ0oH3S9JSBEKuyqw==} cpu: [ppc64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-gnu@4.44.2': resolution: {integrity: sha512-iYtAqBg5eEMG4dEfVlkqo05xMOk6y/JXIToRca2bAWuqjrJYJlx/I7+Z+4hSrsWU8GdJDFPL4ktV3dy4yBSrzg==} cpu: [riscv64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.44.2': resolution: {integrity: sha512-e6vEbgaaqz2yEHqtkPXa28fFuBGmUJ0N2dOJK8YUfijejInt9gfCSA7YDdJ4nYlv67JfP3+PSWFX4IVw/xRIPg==} cpu: [riscv64] os: [linux] - libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.44.2': resolution: {integrity: sha512-evFOtkmVdY3udE+0QKrV5wBx7bKI0iHz5yEVx5WqDJkxp9YQefy4Mpx3RajIVcM6o7jxTvVd/qpC1IXUhGc1Mw==} cpu: [s390x] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.44.2': resolution: {integrity: sha512-/bXb0bEsWMyEkIsUL2Yt5nFB5naLAwyOWMEviQfQY1x3l5WsLKgvZf66TM7UTfED6erckUVUJQ/jJ1FSpm3pRQ==} cpu: [x64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-musl@4.44.2': resolution: {integrity: sha512-3D3OB1vSSBXmkGEZR27uiMRNiwN08/RVAcBKwhUYPaiZ8bcvdeEwWPvbnXvvXHY+A/7xluzcN+kaiOFNiOZwWg==} cpu: [x64] os: [linux] - libc: [musl] '@rollup/rollup-win32-arm64-msvc@4.44.2': resolution: {integrity: sha512-VfU0fsMK+rwdK8mwODqYeM2hDrF2WiHaSmCBrS7gColkQft95/8tphyzv2EupVxn3iE0FI78wzffoULH1G+dkw==} @@ -1166,25 +1151,21 @@ packages: resolution: {integrity: sha512-n7UGSBzv7PiX+V1Q2bY3S1XWyN3RCykCQUgfhZ+xWietCM/1349jgN7DoXKPllqlof1GPGBjziHU0sQZTC4tag==} cpu: [arm64] os: [linux] - libc: [glibc] '@rspack/binding-linux-arm64-musl@1.6.1': resolution: {integrity: sha512-P7nx0jsKxx7g3QAnH9UnJDGVgs1M2H7ZQl68SRyrs42TKOd9Md22ynoMIgCK1zoy+skssU6MhWptluSggXqSrA==} cpu: [arm64] os: [linux] - libc: [musl] '@rspack/binding-linux-x64-gnu@1.6.1': resolution: {integrity: sha512-SdiurC1bV/QHnj7rmrBYJLdsat3uUDWl9KjkVjEbtc8kQV0Ri4/vZRH0nswgzx7hZNY2j0jYuCm5O8+3qeJEMg==} cpu: [x64] os: [linux] - libc: [glibc] '@rspack/binding-linux-x64-musl@1.6.1': resolution: {integrity: sha512-JoSJu29nV+auOePhe8x2Fzqxiga1YGNcOMWKJ5Uj8rHBZ8FPAiiE+CpLG8TwfpHsivojrY/sy6fE8JldYLV5TQ==} cpu: [x64] os: [linux] - libc: [musl] '@rspack/binding-wasm32-wasi@1.6.1': resolution: {integrity: sha512-u5NiSHxM7LtIo4cebq/hQPJ9o39u127am3eVJHDzdmBVhTYYO5l7XVUnFmcU8hNHuj/4lJzkFviWFbf3SaRSYA==} @@ -1249,8 +1230,8 @@ packages: resolution: {integrity: sha512-qJpzYC64kaj3S0fueiu3kXm8xPrR3PcXDPEgnaNMRn0EjNSZFoFjvbUp0YUDsRhN1CB90EnHJtbxWKevnH99UQ==} engines: {node: '>=18.0.0'} - '@smithy/core@3.22.1': - resolution: {integrity: sha512-x3ie6Crr58MWrm4viHqqy2Du2rHYZjwu8BekasrQx4ca+Y24dzVAwq3yErdqIbc2G3I0kLQA13PQ+/rde+u65g==} + '@smithy/core@3.23.0': + resolution: {integrity: sha512-Yq4UPVoQICM9zHnByLmG8632t2M0+yap4T7ANVw482J0W7HW0pOuxwVmeOwzJqX2Q89fkXz0Vybz55Wj2Xzrsg==} engines: {node: '>=18.0.0'} '@smithy/credential-provider-imds@4.2.8': @@ -1313,12 +1294,12 @@ packages: resolution: {integrity: sha512-RO0jeoaYAB1qBRhfVyq0pMgBoUK34YEJxVxyjOWYZiOKOq2yMZ4MnVXMZCUDenpozHue207+9P5ilTV1zeda0A==} engines: {node: '>=18.0.0'} - '@smithy/middleware-endpoint@4.4.13': - resolution: {integrity: sha512-x6vn0PjYmGdNuKh/juUJJewZh7MoQ46jYaJ2mvekF4EesMuFfrl4LaW/k97Zjf8PTCPQmPgMvwewg7eNoH9n5w==} + '@smithy/middleware-endpoint@4.4.14': + resolution: {integrity: sha512-FUFNE5KVeaY6U/GL0nzAAHkaCHzXLZcY1EhtQnsAqhD8Du13oPKtMB9/0WK4/LK6a/T5OZ24wPoSShff5iI6Ag==} engines: {node: '>=18.0.0'} - '@smithy/middleware-retry@4.4.30': - resolution: {integrity: sha512-CBGyFvN0f8hlnqKH/jckRDz78Snrp345+PVk8Ux7pnkUCW97Iinse59lY78hBt04h1GZ6hjBN94BRwZy1xC8Bg==} + '@smithy/middleware-retry@4.4.31': + resolution: {integrity: sha512-RXBzLpMkIrxBPe4C8OmEOHvS8aH9RUuCOH++Acb5jZDEblxDjyg6un72X9IcbrGTJoiUwmI7hLypNfuDACypbg==} engines: {node: '>=18.0.0'} '@smithy/middleware-serde@4.2.9': @@ -1333,8 +1314,8 @@ packages: resolution: {integrity: sha512-aFP1ai4lrbVlWjfpAfRSL8KFcnJQYfTl5QxLJXY32vghJrDuFyPZ6LtUL+JEGYiFRG1PfPLHLoxj107ulncLIg==} engines: {node: '>=18.0.0'} - '@smithy/node-http-handler@4.4.9': - resolution: {integrity: sha512-KX5Wml5mF+luxm1szW4QDz32e3NObgJ4Fyw+irhph4I/2geXwUy4jkIMUs5ZPGflRBeR6BUkC2wqIab4Llgm3w==} + '@smithy/node-http-handler@4.4.10': + resolution: {integrity: sha512-u4YeUwOWRZaHbWaebvrs3UhwQwj+2VNmcVCwXcYTvPIuVyM7Ex1ftAj+fdbG/P4AkBwLq/+SKn+ydOI4ZJE9PA==} engines: {node: '>=18.0.0'} '@smithy/property-provider@4.2.8': @@ -1365,8 +1346,8 @@ packages: resolution: {integrity: sha512-6A4vdGj7qKNRF16UIcO8HhHjKW27thsxYci+5r/uVRkdcBEkOEiY8OMPuydLX4QHSrJqGHPJzPRwwVTqbLZJhg==} engines: {node: '>=18.0.0'} - '@smithy/smithy-client@4.11.2': - resolution: {integrity: sha512-SCkGmFak/xC1n7hKRsUr6wOnBTJ3L22Qd4e8H1fQIuKTAjntwgU8lrdMe7uHdiT2mJAOWA/60qaW9tiMu69n1A==} + '@smithy/smithy-client@4.11.3': + resolution: {integrity: sha512-Q7kY5sDau8OoE6Y9zJoRGgje8P4/UY0WzH8R2ok0PDh+iJ+ZnEKowhjEqYafVcubkbYxQVaqwm3iufktzhprGg==} engines: {node: '>=18.0.0'} '@smithy/types@4.12.0': @@ -1401,12 +1382,12 @@ packages: resolution: {integrity: sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==} engines: {node: '>=18.0.0'} - '@smithy/util-defaults-mode-browser@4.3.29': - resolution: {integrity: sha512-nIGy3DNRmOjaYaaKcQDzmWsro9uxlaqUOhZDHQed9MW/GmkBZPtnU70Pu1+GT9IBmUXwRdDuiyaeiy9Xtpn3+Q==} + '@smithy/util-defaults-mode-browser@4.3.30': + resolution: {integrity: sha512-cMni0uVU27zxOiU8TuC8pQLC1pYeZ/xEMxvchSK/ILwleRd1ugobOcIRr5vXtcRqKd4aBLWlpeBoDPJJ91LQng==} engines: {node: '>=18.0.0'} - '@smithy/util-defaults-mode-node@4.2.32': - resolution: {integrity: sha512-7dtFff6pu5fsjqrVve0YMhrnzJtccCWDacNKOkiZjJ++fmjGExmmSu341x+WU6Oc1IccL7lDuaUj7SfrHpWc5Q==} + '@smithy/util-defaults-mode-node@4.2.33': + resolution: {integrity: sha512-LEb2aq5F4oZUSzWBG7S53d4UytZSkOEJPXcBq/xbG2/TmK9EW5naUZ8lKu1BEyWMzdHIzEVN16M3k8oxDq+DJA==} engines: {node: '>=18.0.0'} '@smithy/util-endpoints@3.2.8': @@ -1425,8 +1406,8 @@ packages: resolution: {integrity: sha512-CfJqwvoRY0kTGe5AkQokpURNCT1u/MkRzMTASWMPPo2hNSnKtF1D45dQl3DE2LKLr4m+PW9mCeBMJr5mCAVThg==} engines: {node: '>=18.0.0'} - '@smithy/util-stream@4.5.11': - resolution: {integrity: sha512-lKmZ0S/3Qj2OF5H1+VzvDLb6kRxGzZHq6f3rAsoSu5cTLGsn3v3VQBA8czkNNXlLjoFEtVu3OQT2jEeOtOE2CA==} + '@smithy/util-stream@4.5.12': + resolution: {integrity: sha512-D8tgkrmhAX/UNeCZbqbEO3uqyghUnEmmoO9YEvRuwxjlkKKUE7FOgCJnqpTlQPe9MApdWPky58mNQQHbnCzoNg==} engines: {node: '>=18.0.0'} '@smithy/util-uri-escape@4.2.0': @@ -4852,31 +4833,31 @@ snapshots: '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 - '@aws-sdk/client-s3@3.981.0': + '@aws-sdk/client-s3@3.989.0': dependencies: '@aws-crypto/sha1-browser': 5.2.0 '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.973.5 - '@aws-sdk/credential-provider-node': 3.972.4 + '@aws-sdk/core': 3.973.9 + '@aws-sdk/credential-provider-node': 3.972.8 '@aws-sdk/middleware-bucket-endpoint': 3.972.3 '@aws-sdk/middleware-expect-continue': 3.972.3 - '@aws-sdk/middleware-flexible-checksums': 3.972.3 + '@aws-sdk/middleware-flexible-checksums': 3.972.7 '@aws-sdk/middleware-host-header': 3.972.3 '@aws-sdk/middleware-location-constraint': 3.972.3 '@aws-sdk/middleware-logger': 3.972.3 '@aws-sdk/middleware-recursion-detection': 3.972.3 - '@aws-sdk/middleware-sdk-s3': 3.972.5 + '@aws-sdk/middleware-sdk-s3': 3.972.9 '@aws-sdk/middleware-ssec': 3.972.3 - '@aws-sdk/middleware-user-agent': 3.972.5 + '@aws-sdk/middleware-user-agent': 3.972.9 '@aws-sdk/region-config-resolver': 3.972.3 - '@aws-sdk/signature-v4-multi-region': 3.981.0 + '@aws-sdk/signature-v4-multi-region': 3.989.0 '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-endpoints': 3.981.0 + '@aws-sdk/util-endpoints': 3.989.0 '@aws-sdk/util-user-agent-browser': 3.972.3 - '@aws-sdk/util-user-agent-node': 3.972.3 + '@aws-sdk/util-user-agent-node': 3.972.7 '@smithy/config-resolver': 4.4.6 - '@smithy/core': 3.22.1 + '@smithy/core': 3.23.0 '@smithy/eventstream-serde-browser': 4.2.8 '@smithy/eventstream-serde-config-resolver': 4.3.8 '@smithy/eventstream-serde-node': 4.2.8 @@ -4887,66 +4868,66 @@ snapshots: '@smithy/invalid-dependency': 4.2.8 '@smithy/md5-js': 4.2.8 '@smithy/middleware-content-length': 4.2.8 - '@smithy/middleware-endpoint': 4.4.13 - '@smithy/middleware-retry': 4.4.30 + '@smithy/middleware-endpoint': 4.4.14 + '@smithy/middleware-retry': 4.4.31 '@smithy/middleware-serde': 4.2.9 '@smithy/middleware-stack': 4.2.8 '@smithy/node-config-provider': 4.3.8 - '@smithy/node-http-handler': 4.4.9 + '@smithy/node-http-handler': 4.4.10 '@smithy/protocol-http': 5.3.8 - '@smithy/smithy-client': 4.11.2 + '@smithy/smithy-client': 4.11.3 '@smithy/types': 4.12.0 '@smithy/url-parser': 4.2.8 '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.29 - '@smithy/util-defaults-mode-node': 4.2.32 + '@smithy/util-defaults-mode-browser': 4.3.30 + '@smithy/util-defaults-mode-node': 4.2.33 '@smithy/util-endpoints': 3.2.8 '@smithy/util-middleware': 4.2.8 '@smithy/util-retry': 4.2.8 - '@smithy/util-stream': 4.5.11 + '@smithy/util-stream': 4.5.12 '@smithy/util-utf8': 4.2.0 '@smithy/util-waiter': 4.2.8 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/client-sso@3.980.0': + '@aws-sdk/client-sso@3.989.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.973.5 + '@aws-sdk/core': 3.973.9 '@aws-sdk/middleware-host-header': 3.972.3 '@aws-sdk/middleware-logger': 3.972.3 '@aws-sdk/middleware-recursion-detection': 3.972.3 - '@aws-sdk/middleware-user-agent': 3.972.5 + '@aws-sdk/middleware-user-agent': 3.972.9 '@aws-sdk/region-config-resolver': 3.972.3 '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-endpoints': 3.980.0 + '@aws-sdk/util-endpoints': 3.989.0 '@aws-sdk/util-user-agent-browser': 3.972.3 - '@aws-sdk/util-user-agent-node': 3.972.3 + '@aws-sdk/util-user-agent-node': 3.972.7 '@smithy/config-resolver': 4.4.6 - '@smithy/core': 3.22.1 + '@smithy/core': 3.23.0 '@smithy/fetch-http-handler': 5.3.9 '@smithy/hash-node': 4.2.8 '@smithy/invalid-dependency': 4.2.8 '@smithy/middleware-content-length': 4.2.8 - '@smithy/middleware-endpoint': 4.4.13 - '@smithy/middleware-retry': 4.4.30 + '@smithy/middleware-endpoint': 4.4.14 + '@smithy/middleware-retry': 4.4.31 '@smithy/middleware-serde': 4.2.9 '@smithy/middleware-stack': 4.2.8 '@smithy/node-config-provider': 4.3.8 - '@smithy/node-http-handler': 4.4.9 + '@smithy/node-http-handler': 4.4.10 '@smithy/protocol-http': 5.3.8 - '@smithy/smithy-client': 4.11.2 + '@smithy/smithy-client': 4.11.3 '@smithy/types': 4.12.0 '@smithy/url-parser': 4.2.8 '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.29 - '@smithy/util-defaults-mode-node': 4.2.32 + '@smithy/util-defaults-mode-browser': 4.3.30 + '@smithy/util-defaults-mode-node': 4.2.33 '@smithy/util-endpoints': 3.2.8 '@smithy/util-middleware': 4.2.8 '@smithy/util-retry': 4.2.8 @@ -4955,16 +4936,16 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/core@3.973.5': + '@aws-sdk/core@3.973.9': dependencies: '@aws-sdk/types': 3.973.1 - '@aws-sdk/xml-builder': 3.972.3 - '@smithy/core': 3.22.1 + '@aws-sdk/xml-builder': 3.972.4 + '@smithy/core': 3.23.0 '@smithy/node-config-provider': 4.3.8 '@smithy/property-provider': 4.2.8 '@smithy/protocol-http': 5.3.8 '@smithy/signature-v4': 5.3.8 - '@smithy/smithy-client': 4.11.2 + '@smithy/smithy-client': 4.11.3 '@smithy/types': 4.12.0 '@smithy/util-base64': 4.3.0 '@smithy/util-middleware': 4.2.8 @@ -4976,37 +4957,37 @@ snapshots: '@smithy/types': 4.12.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-env@3.972.3': + '@aws-sdk/credential-provider-env@3.972.7': dependencies: - '@aws-sdk/core': 3.973.5 + '@aws-sdk/core': 3.973.9 '@aws-sdk/types': 3.973.1 '@smithy/property-provider': 4.2.8 '@smithy/types': 4.12.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-http@3.972.5': + '@aws-sdk/credential-provider-http@3.972.9': dependencies: - '@aws-sdk/core': 3.973.5 + '@aws-sdk/core': 3.973.9 '@aws-sdk/types': 3.973.1 '@smithy/fetch-http-handler': 5.3.9 - '@smithy/node-http-handler': 4.4.9 + '@smithy/node-http-handler': 4.4.10 '@smithy/property-provider': 4.2.8 '@smithy/protocol-http': 5.3.8 - '@smithy/smithy-client': 4.11.2 + '@smithy/smithy-client': 4.11.3 '@smithy/types': 4.12.0 - '@smithy/util-stream': 4.5.11 + '@smithy/util-stream': 4.5.12 tslib: 2.8.1 - '@aws-sdk/credential-provider-ini@3.972.3': + '@aws-sdk/credential-provider-ini@3.972.7': dependencies: - '@aws-sdk/core': 3.973.5 - '@aws-sdk/credential-provider-env': 3.972.3 - '@aws-sdk/credential-provider-http': 3.972.5 - '@aws-sdk/credential-provider-login': 3.972.3 - '@aws-sdk/credential-provider-process': 3.972.3 - '@aws-sdk/credential-provider-sso': 3.972.3 - '@aws-sdk/credential-provider-web-identity': 3.972.3 - '@aws-sdk/nested-clients': 3.980.0 + '@aws-sdk/core': 3.973.9 + '@aws-sdk/credential-provider-env': 3.972.7 + '@aws-sdk/credential-provider-http': 3.972.9 + '@aws-sdk/credential-provider-login': 3.972.7 + '@aws-sdk/credential-provider-process': 3.972.7 + '@aws-sdk/credential-provider-sso': 3.972.7 + '@aws-sdk/credential-provider-web-identity': 3.972.7 + '@aws-sdk/nested-clients': 3.989.0 '@aws-sdk/types': 3.973.1 '@smithy/credential-provider-imds': 4.2.8 '@smithy/property-provider': 4.2.8 @@ -5016,10 +4997,10 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-login@3.972.3': + '@aws-sdk/credential-provider-login@3.972.7': dependencies: - '@aws-sdk/core': 3.973.5 - '@aws-sdk/nested-clients': 3.980.0 + '@aws-sdk/core': 3.973.9 + '@aws-sdk/nested-clients': 3.989.0 '@aws-sdk/types': 3.973.1 '@smithy/property-provider': 4.2.8 '@smithy/protocol-http': 5.3.8 @@ -5029,14 +5010,14 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-node@3.972.4': + '@aws-sdk/credential-provider-node@3.972.8': dependencies: - '@aws-sdk/credential-provider-env': 3.972.3 - '@aws-sdk/credential-provider-http': 3.972.5 - '@aws-sdk/credential-provider-ini': 3.972.3 - '@aws-sdk/credential-provider-process': 3.972.3 - '@aws-sdk/credential-provider-sso': 3.972.3 - '@aws-sdk/credential-provider-web-identity': 3.972.3 + '@aws-sdk/credential-provider-env': 3.972.7 + '@aws-sdk/credential-provider-http': 3.972.9 + '@aws-sdk/credential-provider-ini': 3.972.7 + '@aws-sdk/credential-provider-process': 3.972.7 + '@aws-sdk/credential-provider-sso': 3.972.7 + '@aws-sdk/credential-provider-web-identity': 3.972.7 '@aws-sdk/types': 3.973.1 '@smithy/credential-provider-imds': 4.2.8 '@smithy/property-provider': 4.2.8 @@ -5046,20 +5027,20 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-process@3.972.3': + '@aws-sdk/credential-provider-process@3.972.7': dependencies: - '@aws-sdk/core': 3.973.5 + '@aws-sdk/core': 3.973.9 '@aws-sdk/types': 3.973.1 '@smithy/property-provider': 4.2.8 '@smithy/shared-ini-file-loader': 4.4.3 '@smithy/types': 4.12.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-sso@3.972.3': + '@aws-sdk/credential-provider-sso@3.972.7': dependencies: - '@aws-sdk/client-sso': 3.980.0 - '@aws-sdk/core': 3.973.5 - '@aws-sdk/token-providers': 3.980.0 + '@aws-sdk/client-sso': 3.989.0 + '@aws-sdk/core': 3.973.9 + '@aws-sdk/token-providers': 3.989.0 '@aws-sdk/types': 3.973.1 '@smithy/property-provider': 4.2.8 '@smithy/shared-ini-file-loader': 4.4.3 @@ -5068,10 +5049,10 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-web-identity@3.972.3': + '@aws-sdk/credential-provider-web-identity@3.972.7': dependencies: - '@aws-sdk/core': 3.973.5 - '@aws-sdk/nested-clients': 3.980.0 + '@aws-sdk/core': 3.973.9 + '@aws-sdk/nested-clients': 3.989.0 '@aws-sdk/types': 3.973.1 '@smithy/property-provider': 4.2.8 '@smithy/shared-ini-file-loader': 4.4.3 @@ -5097,12 +5078,12 @@ snapshots: '@smithy/types': 4.12.0 tslib: 2.8.1 - '@aws-sdk/middleware-flexible-checksums@3.972.3': + '@aws-sdk/middleware-flexible-checksums@3.972.7': dependencies: '@aws-crypto/crc32': 5.2.0 '@aws-crypto/crc32c': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/core': 3.973.5 + '@aws-sdk/core': 3.973.9 '@aws-sdk/crc64-nvme': 3.972.0 '@aws-sdk/types': 3.973.1 '@smithy/is-array-buffer': 4.2.0 @@ -5110,7 +5091,7 @@ snapshots: '@smithy/protocol-http': 5.3.8 '@smithy/types': 4.12.0 '@smithy/util-middleware': 4.2.8 - '@smithy/util-stream': 4.5.11 + '@smithy/util-stream': 4.5.12 '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 @@ -5141,20 +5122,20 @@ snapshots: '@smithy/types': 4.12.0 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-s3@3.972.5': + '@aws-sdk/middleware-sdk-s3@3.972.9': dependencies: - '@aws-sdk/core': 3.973.5 + '@aws-sdk/core': 3.973.9 '@aws-sdk/types': 3.973.1 '@aws-sdk/util-arn-parser': 3.972.2 - '@smithy/core': 3.22.1 + '@smithy/core': 3.23.0 '@smithy/node-config-provider': 4.3.8 '@smithy/protocol-http': 5.3.8 '@smithy/signature-v4': 5.3.8 - '@smithy/smithy-client': 4.11.2 + '@smithy/smithy-client': 4.11.3 '@smithy/types': 4.12.0 '@smithy/util-config-provider': 4.2.0 '@smithy/util-middleware': 4.2.8 - '@smithy/util-stream': 4.5.11 + '@smithy/util-stream': 4.5.12 '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 @@ -5164,51 +5145,51 @@ snapshots: '@smithy/types': 4.12.0 tslib: 2.8.1 - '@aws-sdk/middleware-user-agent@3.972.5': + '@aws-sdk/middleware-user-agent@3.972.9': dependencies: - '@aws-sdk/core': 3.973.5 + '@aws-sdk/core': 3.973.9 '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-endpoints': 3.980.0 - '@smithy/core': 3.22.1 + '@aws-sdk/util-endpoints': 3.989.0 + '@smithy/core': 3.23.0 '@smithy/protocol-http': 5.3.8 '@smithy/types': 4.12.0 tslib: 2.8.1 - '@aws-sdk/nested-clients@3.980.0': + '@aws-sdk/nested-clients@3.989.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.973.5 + '@aws-sdk/core': 3.973.9 '@aws-sdk/middleware-host-header': 3.972.3 '@aws-sdk/middleware-logger': 3.972.3 '@aws-sdk/middleware-recursion-detection': 3.972.3 - '@aws-sdk/middleware-user-agent': 3.972.5 + '@aws-sdk/middleware-user-agent': 3.972.9 '@aws-sdk/region-config-resolver': 3.972.3 '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-endpoints': 3.980.0 + '@aws-sdk/util-endpoints': 3.989.0 '@aws-sdk/util-user-agent-browser': 3.972.3 - '@aws-sdk/util-user-agent-node': 3.972.3 + '@aws-sdk/util-user-agent-node': 3.972.7 '@smithy/config-resolver': 4.4.6 - '@smithy/core': 3.22.1 + '@smithy/core': 3.23.0 '@smithy/fetch-http-handler': 5.3.9 '@smithy/hash-node': 4.2.8 '@smithy/invalid-dependency': 4.2.8 '@smithy/middleware-content-length': 4.2.8 - '@smithy/middleware-endpoint': 4.4.13 - '@smithy/middleware-retry': 4.4.30 + '@smithy/middleware-endpoint': 4.4.14 + '@smithy/middleware-retry': 4.4.31 '@smithy/middleware-serde': 4.2.9 '@smithy/middleware-stack': 4.2.8 '@smithy/node-config-provider': 4.3.8 - '@smithy/node-http-handler': 4.4.9 + '@smithy/node-http-handler': 4.4.10 '@smithy/protocol-http': 5.3.8 - '@smithy/smithy-client': 4.11.2 + '@smithy/smithy-client': 4.11.3 '@smithy/types': 4.12.0 '@smithy/url-parser': 4.2.8 '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.29 - '@smithy/util-defaults-mode-node': 4.2.32 + '@smithy/util-defaults-mode-browser': 4.3.30 + '@smithy/util-defaults-mode-node': 4.2.33 '@smithy/util-endpoints': 3.2.8 '@smithy/util-middleware': 4.2.8 '@smithy/util-retry': 4.2.8 @@ -5225,19 +5206,19 @@ snapshots: '@smithy/types': 4.12.0 tslib: 2.8.1 - '@aws-sdk/signature-v4-multi-region@3.981.0': + '@aws-sdk/signature-v4-multi-region@3.989.0': dependencies: - '@aws-sdk/middleware-sdk-s3': 3.972.5 + '@aws-sdk/middleware-sdk-s3': 3.972.9 '@aws-sdk/types': 3.973.1 '@smithy/protocol-http': 5.3.8 '@smithy/signature-v4': 5.3.8 '@smithy/types': 4.12.0 tslib: 2.8.1 - '@aws-sdk/token-providers@3.980.0': + '@aws-sdk/token-providers@3.989.0': dependencies: - '@aws-sdk/core': 3.973.5 - '@aws-sdk/nested-clients': 3.980.0 + '@aws-sdk/core': 3.973.9 + '@aws-sdk/nested-clients': 3.989.0 '@aws-sdk/types': 3.973.1 '@smithy/property-provider': 4.2.8 '@smithy/shared-ini-file-loader': 4.4.3 @@ -5255,15 +5236,7 @@ snapshots: dependencies: tslib: 2.8.1 - '@aws-sdk/util-endpoints@3.980.0': - dependencies: - '@aws-sdk/types': 3.973.1 - '@smithy/types': 4.12.0 - '@smithy/url-parser': 4.2.8 - '@smithy/util-endpoints': 3.2.8 - tslib: 2.8.1 - - '@aws-sdk/util-endpoints@3.981.0': + '@aws-sdk/util-endpoints@3.989.0': dependencies: '@aws-sdk/types': 3.973.1 '@smithy/types': 4.12.0 @@ -5282,15 +5255,15 @@ snapshots: bowser: 2.13.1 tslib: 2.8.1 - '@aws-sdk/util-user-agent-node@3.972.3': + '@aws-sdk/util-user-agent-node@3.972.7': dependencies: - '@aws-sdk/middleware-user-agent': 3.972.5 + '@aws-sdk/middleware-user-agent': 3.972.9 '@aws-sdk/types': 3.973.1 '@smithy/node-config-provider': 4.3.8 '@smithy/types': 4.12.0 tslib: 2.8.1 - '@aws-sdk/xml-builder@3.972.3': + '@aws-sdk/xml-builder@3.972.4': dependencies: '@smithy/types': 4.12.0 fast-xml-parser: 5.3.4 @@ -5983,7 +5956,7 @@ snapshots: '@smithy/util-middleware': 4.2.8 tslib: 2.8.1 - '@smithy/core@3.22.1': + '@smithy/core@3.23.0': dependencies: '@smithy/middleware-serde': 4.2.9 '@smithy/protocol-http': 5.3.8 @@ -5991,7 +5964,7 @@ snapshots: '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 '@smithy/util-middleware': 4.2.8 - '@smithy/util-stream': 4.5.11 + '@smithy/util-stream': 4.5.12 '@smithy/util-utf8': 4.2.0 '@smithy/uuid': 1.1.0 tslib: 2.8.1 @@ -6087,9 +6060,9 @@ snapshots: '@smithy/types': 4.12.0 tslib: 2.8.1 - '@smithy/middleware-endpoint@4.4.13': + '@smithy/middleware-endpoint@4.4.14': dependencies: - '@smithy/core': 3.22.1 + '@smithy/core': 3.23.0 '@smithy/middleware-serde': 4.2.9 '@smithy/node-config-provider': 4.3.8 '@smithy/shared-ini-file-loader': 4.4.3 @@ -6098,12 +6071,12 @@ snapshots: '@smithy/util-middleware': 4.2.8 tslib: 2.8.1 - '@smithy/middleware-retry@4.4.30': + '@smithy/middleware-retry@4.4.31': dependencies: '@smithy/node-config-provider': 4.3.8 '@smithy/protocol-http': 5.3.8 '@smithy/service-error-classification': 4.2.8 - '@smithy/smithy-client': 4.11.2 + '@smithy/smithy-client': 4.11.3 '@smithy/types': 4.12.0 '@smithy/util-middleware': 4.2.8 '@smithy/util-retry': 4.2.8 @@ -6128,7 +6101,7 @@ snapshots: '@smithy/types': 4.12.0 tslib: 2.8.1 - '@smithy/node-http-handler@4.4.9': + '@smithy/node-http-handler@4.4.10': dependencies: '@smithy/abort-controller': 4.2.8 '@smithy/protocol-http': 5.3.8 @@ -6177,14 +6150,14 @@ snapshots: '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 - '@smithy/smithy-client@4.11.2': + '@smithy/smithy-client@4.11.3': dependencies: - '@smithy/core': 3.22.1 - '@smithy/middleware-endpoint': 4.4.13 + '@smithy/core': 3.23.0 + '@smithy/middleware-endpoint': 4.4.14 '@smithy/middleware-stack': 4.2.8 '@smithy/protocol-http': 5.3.8 '@smithy/types': 4.12.0 - '@smithy/util-stream': 4.5.11 + '@smithy/util-stream': 4.5.12 tslib: 2.8.1 '@smithy/types@4.12.0': @@ -6225,20 +6198,20 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/util-defaults-mode-browser@4.3.29': + '@smithy/util-defaults-mode-browser@4.3.30': dependencies: '@smithy/property-provider': 4.2.8 - '@smithy/smithy-client': 4.11.2 + '@smithy/smithy-client': 4.11.3 '@smithy/types': 4.12.0 tslib: 2.8.1 - '@smithy/util-defaults-mode-node@4.2.32': + '@smithy/util-defaults-mode-node@4.2.33': dependencies: '@smithy/config-resolver': 4.4.6 '@smithy/credential-provider-imds': 4.2.8 '@smithy/node-config-provider': 4.3.8 '@smithy/property-provider': 4.2.8 - '@smithy/smithy-client': 4.11.2 + '@smithy/smithy-client': 4.11.3 '@smithy/types': 4.12.0 tslib: 2.8.1 @@ -6263,10 +6236,10 @@ snapshots: '@smithy/types': 4.12.0 tslib: 2.8.1 - '@smithy/util-stream@4.5.11': + '@smithy/util-stream@4.5.12': dependencies: '@smithy/fetch-http-handler': 5.3.9 - '@smithy/node-http-handler': 4.4.9 + '@smithy/node-http-handler': 4.4.10 '@smithy/types': 4.12.0 '@smithy/util-base64': 4.3.0 '@smithy/util-buffer-from': 4.2.0 From 69e267271e2a4e8d2bc139291584342f7613fe45 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sun, 15 Feb 2026 17:24:51 +0900 Subject: [PATCH 11/15] Update pnpm-lock.yaml --- pnpm-lock.yaml | 247 ++++++++++++++++++++++++------------------------- 1 file changed, 121 insertions(+), 126 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c6f110b75..b26d7c286 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,7 +13,7 @@ importers: version: 2.66.7(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@aws-sdk/client-s3': specifier: ^3.989.0 - version: 3.989.0 + version: 3.990.0 '@dnd-kit/core': specifier: ^6.3.1 version: 6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -251,52 +251,52 @@ packages: '@aws-crypto/util@5.2.0': resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} - '@aws-sdk/client-s3@3.989.0': - resolution: {integrity: sha512-ccz2miIetWAgrJYmKCpSnRjF8jew7DPstl54nufhfPMtM1MLxD2z55eSk1eJj3Umhu4CioNN1aY1ILT7fwlSiw==} + '@aws-sdk/client-s3@3.990.0': + resolution: {integrity: sha512-XnsM8RgB35Atn2+aYSocitCybDG82x9yYf/s2D23ytpyHCupmuZN3LzK2a0WxmKO6Zf7EtEIYy0mHGY4tLp9YA==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-sso@3.989.0': - resolution: {integrity: sha512-3sC+J1ru5VFXLgt9KZmXto0M7mnV5RkS6FNGwRMK3XrojSjHso9DLOWjbnXhbNv4motH8vu53L1HK2VC1+Nj5w==} + '@aws-sdk/client-sso@3.990.0': + resolution: {integrity: sha512-xTEaPjZwOqVjGbLOP7qzwbdOWJOo1ne2mUhTZwEBBkPvNk4aXB/vcYwWwrjoSWUqtit4+GDbO75ePc/S6TUJYQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/core@3.973.9': - resolution: {integrity: sha512-cyUOfJSizn8da7XrBEFBf4UMI4A6JQNX6ZFcKtYmh/CrwfzsDcabv3k/z0bNwQ3pX5aeq5sg/8Bs/ASiL0bJaA==} + '@aws-sdk/core@3.973.10': + resolution: {integrity: sha512-4u/FbyyT3JqzfsESI70iFg6e2yp87MB5kS2qcxIA66m52VSTN1fvuvbCY1h/LKq1LvuxIrlJ1ItcyjvcKoaPLg==} engines: {node: '>=20.0.0'} '@aws-sdk/crc64-nvme@3.972.0': resolution: {integrity: sha512-ThlLhTqX68jvoIVv+pryOdb5coP1cX1/MaTbB9xkGDCbWbsqQcLqzPxuSoW1DCnAAIacmXCWpzUNOB9pv+xXQw==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-env@3.972.7': - resolution: {integrity: sha512-r8kBtglvLjGxBT87l6Lqkh9fL8yJJ6O4CYQPjKlj3AkCuL4/4784x3rxxXWw9LTKXOo114VB6mjxAuy5pI7XIg==} + '@aws-sdk/credential-provider-env@3.972.8': + resolution: {integrity: sha512-r91OOPAcHnLCSxaeu/lzZAVRCZ/CtTNuwmJkUwpwSDshUrP7bkX1OmFn2nUMWd9kN53Q4cEo8b7226G4olt2Mg==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-http@3.972.9': - resolution: {integrity: sha512-40caFblEg/TPrp9EpvyMxp4xlJ5TuTI+A8H6g8FhHn2hfH2PObFAPLF9d5AljK/G69E1YtTklkuQeAwPlV3w8Q==} + '@aws-sdk/credential-provider-http@3.972.10': + resolution: {integrity: sha512-DTtuyXSWB+KetzLcWaSahLJCtTUe/3SXtlGp4ik9PCe9xD6swHEkG8n8/BNsQ9dsihb9nhFvuUB4DpdBGDcvVg==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-ini@3.972.7': - resolution: {integrity: sha512-zeYKrMwM5bCkHFho/x3+1OL0vcZQ0OhTR7k35tLq74+GP5ieV3juHXTZfa2LVE0Bg75cHIIerpX0gomVOhzo/w==} + '@aws-sdk/credential-provider-ini@3.972.8': + resolution: {integrity: sha512-n2dMn21gvbBIEh00E8Nb+j01U/9rSqFIamWRdGm/mE5e+vHQ9g0cBNdrYFlM6AAiryKVHZmShWT9D1JAWJ3ISw==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-login@3.972.7': - resolution: {integrity: sha512-Q103cLU6OjAllYjX7+V+PKQw654jjvZUkD+lbUUiFbqut6gR5zwl1DrelvJPM5hnzIty7BCaxaRB3KMuz3M/ug==} + '@aws-sdk/credential-provider-login@3.972.8': + resolution: {integrity: sha512-rMFuVids8ICge/X9DF5pRdGMIvkVhDV9IQFQ8aTYk6iF0rl9jOUa1C3kjepxiXUlpgJQT++sLZkT9n0TMLHhQw==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-node@3.972.8': - resolution: {integrity: sha512-AaDVOT7iNJyLjc3j91VlucPZ4J8Bw+eu9sllRDugJqhHWYyR3Iyp2huBUW8A3+DfHoh70sxGkY92cThAicSzlQ==} + '@aws-sdk/credential-provider-node@3.972.9': + resolution: {integrity: sha512-LfJfO0ClRAq2WsSnA9JuUsNyIicD2eyputxSlSL0EiMrtxOxELLRG6ZVYDf/a1HCepaYPXeakH4y8D5OLCauag==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-process@3.972.7': - resolution: {integrity: sha512-hxMo1V3ujWWrQSONxQJAElnjredkRpB6p8SDjnvRq70IwYY38R/CZSys0IbhRPxdgWZ5j12yDRk2OXhxw4Gj3g==} + '@aws-sdk/credential-provider-process@3.972.8': + resolution: {integrity: sha512-6cg26ffFltxM51OOS8NH7oE41EccaYiNlbd5VgUYwhiGCySLfHoGuGrLm2rMB4zhy+IO5nWIIG0HiodX8zdvHA==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-sso@3.972.7': - resolution: {integrity: sha512-ZGKBOHEj8Ap15jhG2XMncQmKLTqA++2DVU2eZfLu3T/pkwDyhCp5eZv5c/acFxbZcA/6mtxke+vzO/n+aeHs4A==} + '@aws-sdk/credential-provider-sso@3.972.8': + resolution: {integrity: sha512-35kqmFOVU1n26SNv+U37sM8b2TzG8LyqAcd6iM9gprqxyHEh/8IM3gzN4Jzufs3qM6IrH8e43ryZWYdvfVzzKQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-web-identity@3.972.7': - resolution: {integrity: sha512-AbYupBIoSJoVMlbMqBhNvPhqj+CdGtzW7Uk4ZIMBm2br18pc3rkG1VaKVFV85H87QCvLHEnni1idJjaX1wOmIw==} + '@aws-sdk/credential-provider-web-identity@3.972.8': + resolution: {integrity: sha512-CZhN1bOc1J3ubQPqbmr5b4KaMJBgdDvYsmEIZuX++wFlzmZsKj1bwkaiTEb5U2V7kXuzLlpF5HJSOM9eY/6nGA==} engines: {node: '>=20.0.0'} '@aws-sdk/middleware-bucket-endpoint@3.972.3': @@ -307,8 +307,8 @@ packages: resolution: {integrity: sha512-4msC33RZsXQpUKR5QR4HnvBSNCPLGHmB55oDiROqqgyOc+TOfVu2xgi5goA7ms6MdZLeEh2905UfWMnMMF4mRg==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-flexible-checksums@3.972.7': - resolution: {integrity: sha512-YU/5rpz8k2mwFGi2M0px9ChOQZY7Bbow5knB2WLRVPqDM/cG8T5zj55UaWS1qcaFpE7vCX9a9/kvYBlKGcD+KA==} + '@aws-sdk/middleware-flexible-checksums@3.972.8': + resolution: {integrity: sha512-Hn6gumcN/3/8Fzo9z7N1pA2PRfE8S+qAqdb4g3MqzXjIOIe+VxD7edO/DKAJ1YH11639EGQIHBz0wdOb5btjtw==} engines: {node: '>=20.0.0'} '@aws-sdk/middleware-host-header@3.972.3': @@ -327,32 +327,32 @@ packages: resolution: {integrity: sha512-PY57QhzNuXHnwbJgbWYTrqIDHYSeOlhfYERTAuc16LKZpTZRJUjzBFokp9hF7u1fuGeE3D70ERXzdbMBOqQz7Q==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-sdk-s3@3.972.9': - resolution: {integrity: sha512-F4Ak2HM7te/o3izFTqg/jUTBLjavpaJ5iynKM6aLMwNddXbwAZQ1VbIG8RFUHBo7fBHj2eeN2FNLtIFT4ejWYQ==} + '@aws-sdk/middleware-sdk-s3@3.972.10': + resolution: {integrity: sha512-wLkB4bshbBtsAiC2WwlHzOWXu1fx3ftL63fQl0DxEda48Q6B8bcHydZppE3KjEIpPyiNOllByfSnb07cYpIgmw==} engines: {node: '>=20.0.0'} '@aws-sdk/middleware-ssec@3.972.3': resolution: {integrity: sha512-dU6kDuULN3o3jEHcjm0c4zWJlY1zWVkjG9NPe9qxYLLpcbdj5kRYBS2DdWYD+1B9f910DezRuws7xDEqKkHQIg==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-user-agent@3.972.9': - resolution: {integrity: sha512-1g1B7yf7KzessB0mKNiV9gAHEwbM662xgU+VE4LxyGe6kVGZ8LqYsngjhE+Stna09CJ7Pxkjr6Uq1OtbGwJJJg==} + '@aws-sdk/middleware-user-agent@3.972.10': + resolution: {integrity: sha512-bBEL8CAqPQkI91ZM5a9xnFAzedpzH6NYCOtNyLarRAzTUTFN2DKqaC60ugBa7pnU1jSi4mA7WAXBsrod7nJltg==} engines: {node: '>=20.0.0'} - '@aws-sdk/nested-clients@3.989.0': - resolution: {integrity: sha512-Dbk2HMPU3mb6RrSRzgf0WCaWSbgtZG258maCpuN2/ONcAQNpOTw99V5fU5CA1qVK6Vkm4Fwj2cnOnw7wbGVlOw==} + '@aws-sdk/nested-clients@3.990.0': + resolution: {integrity: sha512-3NA0s66vsy8g7hPh36ZsUgO4SiMyrhwcYvuuNK1PezO52vX3hXDW4pQrC6OQLGKGJV0o6tbEyQtXb/mPs8zg8w==} engines: {node: '>=20.0.0'} '@aws-sdk/region-config-resolver@3.972.3': resolution: {integrity: sha512-v4J8qYAWfOMcZ4MJUyatntOicTzEMaU7j3OpkRCGGFSL2NgXQ5VbxauIyORA+pxdKZ0qQG2tCQjQjZDlXEC3Ow==} engines: {node: '>=20.0.0'} - '@aws-sdk/signature-v4-multi-region@3.989.0': - resolution: {integrity: sha512-rVhR/BUZdnru7tLlxWD+uzoKB1LAs2L0pcoh6rYgIYuCtQflnsC6Ud0SpfqIsOapBSBKXdoW73IITFf+XFMdCQ==} + '@aws-sdk/signature-v4-multi-region@3.990.0': + resolution: {integrity: sha512-O55s1eFmKi+2Ko5T1hbdxL6tFVONGscSVe9VRxS4m91Tlbo9iG2Q2HvKWq1DuKQAuUWSUfMmjrRt07JNzizr2A==} engines: {node: '>=20.0.0'} - '@aws-sdk/token-providers@3.989.0': - resolution: {integrity: sha512-OdBByMv+OjOZoekrk4THPFpLuND5aIQbDHCGh3n2rvifAbm31+6e0OLhxSeCF1UMPm+nKq12bXYYEoCIx5SQBg==} + '@aws-sdk/token-providers@3.990.0': + resolution: {integrity: sha512-L3BtUb2v9XmYgQdfGBzbBtKMXaP5fV973y3Qdxeevs6oUTVXFmi/mV1+LnScA/1wVPJC9/hlK+1o5vbt7cG7EQ==} engines: {node: '>=20.0.0'} '@aws-sdk/types@3.973.1': @@ -363,8 +363,8 @@ packages: resolution: {integrity: sha512-VkykWbqMjlSgBFDyrY3nOSqupMc6ivXuGmvci6Q3NnLq5kC+mKQe2QBZ4nrWRE/jqOxeFP2uYzLtwncYYcvQDg==} engines: {node: '>=20.0.0'} - '@aws-sdk/util-endpoints@3.989.0': - resolution: {integrity: sha512-eKmAOeQM4Qusq0jtcbZPiNWky8XaojByKC/n+THbJ8vJf7t4ys8LlcZ4PrBSHZISe9cC484mQsPVOQh6iySjqw==} + '@aws-sdk/util-endpoints@3.990.0': + resolution: {integrity: sha512-kVwtDc9LNI3tQZHEMNbkLIOpeDK8sRSTuT8eMnzGY+O+JImPisfSTjdh+jw9OTznu+MYZjQsv0258sazVKunYg==} engines: {node: '>=20.0.0'} '@aws-sdk/util-locate-window@3.965.4': @@ -374,8 +374,8 @@ packages: '@aws-sdk/util-user-agent-browser@3.972.3': resolution: {integrity: sha512-JurOwkRUcXD/5MTDBcqdyQ9eVedtAsZgw5rBwktsPTN7QtPiS2Ld1jkJepNgYoCufz1Wcut9iup7GJDoIHp8Fw==} - '@aws-sdk/util-user-agent-node@3.972.7': - resolution: {integrity: sha512-oyhv+FjrgHjP+F16cmsrJzNP4qaRJzkV1n9Lvv4uyh3kLqo3rIe9NSBSBa35f2TedczfG2dD+kaQhHBB47D6Og==} + '@aws-sdk/util-user-agent-node@3.972.8': + resolution: {integrity: sha512-XJZuT0LWsFCW1C8dEpPAXSa7h6Pb3krr2y//1X0Zidpcl0vmgY5nL/X0JuBZlntpBzaN3+U4hvKjuijyiiR8zw==} engines: {node: '>=20.0.0'} peerDependencies: aws-crt: '>=1.0.0' @@ -1290,9 +1290,6 @@ packages: '@rspack/lite-tapable@1.1.0': resolution: {integrity: sha512-E2B0JhYFmVAwdDiG14+DW0Di4Ze4Jg10Pc4/lILUrd5DRCaklduz2OvJ5HYQ6G+hd+WTzqQb3QnDNfK4yvAFYw==} - '@standard-schema/spec@1.1.0': - resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} - '@smithy/abort-controller@4.2.8': resolution: {integrity: sha512-peuVfkYHAmS5ybKxWcfraK7WBBP0J+rkfUcbHJJKQ4ir3UAUNQI+Y4Vt/PqSzGqgloJ5O1dk7+WzNL8wcCSXbw==} engines: {node: '>=18.0.0'} @@ -1509,6 +1506,9 @@ packages: resolution: {integrity: sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==} engines: {node: '>=18.0.0'} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@swc/helpers@0.5.17': resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} @@ -2092,8 +2092,8 @@ packages: bonjour-service@1.3.0: resolution: {integrity: sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==} - bowser@2.13.1: - resolution: {integrity: sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw==} + bowser@2.14.1: + resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==} brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} @@ -2687,14 +2687,14 @@ packages: fast-uri@3.0.3: resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} - fast-xml-parser@5.3.5: - resolution: {integrity: sha512-JeaA2Vm9ffQKp9VjvfzObuMCjUYAp5WDYhRYL5LrBPY/jUDlUtOvDfot0vKSkB9tuX885BDHjtw4fZadD95wnA==} - hasBin: true - fast-xml-parser@5.3.4: resolution: {integrity: sha512-EFd6afGmXlCx8H8WTZHhAoDaWaGyuIBoZJ2mknrNxug+aZKjkp0a0dlars9Izl+jF+7Gu1/5f/2h68cQpe0IiA==} hasBin: true + fast-xml-parser@5.3.5: + resolution: {integrity: sha512-JeaA2Vm9ffQKp9VjvfzObuMCjUYAp5WDYhRYL5LrBPY/jUDlUtOvDfot0vKSkB9tuX885BDHjtw4fZadD95wnA==} + hasBin: true + fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -4092,9 +4092,6 @@ packages: strnum@2.1.2: resolution: {integrity: sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==} - strnum@2.1.2: - resolution: {integrity: sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==} - supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -4712,29 +4709,29 @@ snapshots: '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 - '@aws-sdk/client-s3@3.989.0': + '@aws-sdk/client-s3@3.990.0': dependencies: '@aws-crypto/sha1-browser': 5.2.0 '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.973.9 - '@aws-sdk/credential-provider-node': 3.972.8 + '@aws-sdk/core': 3.973.10 + '@aws-sdk/credential-provider-node': 3.972.9 '@aws-sdk/middleware-bucket-endpoint': 3.972.3 '@aws-sdk/middleware-expect-continue': 3.972.3 - '@aws-sdk/middleware-flexible-checksums': 3.972.7 + '@aws-sdk/middleware-flexible-checksums': 3.972.8 '@aws-sdk/middleware-host-header': 3.972.3 '@aws-sdk/middleware-location-constraint': 3.972.3 '@aws-sdk/middleware-logger': 3.972.3 '@aws-sdk/middleware-recursion-detection': 3.972.3 - '@aws-sdk/middleware-sdk-s3': 3.972.9 + '@aws-sdk/middleware-sdk-s3': 3.972.10 '@aws-sdk/middleware-ssec': 3.972.3 - '@aws-sdk/middleware-user-agent': 3.972.9 + '@aws-sdk/middleware-user-agent': 3.972.10 '@aws-sdk/region-config-resolver': 3.972.3 - '@aws-sdk/signature-v4-multi-region': 3.989.0 + '@aws-sdk/signature-v4-multi-region': 3.990.0 '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-endpoints': 3.989.0 + '@aws-sdk/util-endpoints': 3.990.0 '@aws-sdk/util-user-agent-browser': 3.972.3 - '@aws-sdk/util-user-agent-node': 3.972.7 + '@aws-sdk/util-user-agent-node': 3.972.8 '@smithy/config-resolver': 4.4.6 '@smithy/core': 3.23.0 '@smithy/eventstream-serde-browser': 4.2.8 @@ -4772,20 +4769,20 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/client-sso@3.989.0': + '@aws-sdk/client-sso@3.990.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.973.9 + '@aws-sdk/core': 3.973.10 '@aws-sdk/middleware-host-header': 3.972.3 '@aws-sdk/middleware-logger': 3.972.3 '@aws-sdk/middleware-recursion-detection': 3.972.3 - '@aws-sdk/middleware-user-agent': 3.972.9 + '@aws-sdk/middleware-user-agent': 3.972.10 '@aws-sdk/region-config-resolver': 3.972.3 '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-endpoints': 3.989.0 + '@aws-sdk/util-endpoints': 3.990.0 '@aws-sdk/util-user-agent-browser': 3.972.3 - '@aws-sdk/util-user-agent-node': 3.972.7 + '@aws-sdk/util-user-agent-node': 3.972.8 '@smithy/config-resolver': 4.4.6 '@smithy/core': 3.23.0 '@smithy/fetch-http-handler': 5.3.9 @@ -4815,7 +4812,7 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/core@3.973.9': + '@aws-sdk/core@3.973.10': dependencies: '@aws-sdk/types': 3.973.1 '@aws-sdk/xml-builder': 3.972.4 @@ -4836,17 +4833,17 @@ snapshots: '@smithy/types': 4.12.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-env@3.972.7': + '@aws-sdk/credential-provider-env@3.972.8': dependencies: - '@aws-sdk/core': 3.973.9 + '@aws-sdk/core': 3.973.10 '@aws-sdk/types': 3.973.1 '@smithy/property-provider': 4.2.8 '@smithy/types': 4.12.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-http@3.972.9': + '@aws-sdk/credential-provider-http@3.972.10': dependencies: - '@aws-sdk/core': 3.973.9 + '@aws-sdk/core': 3.973.10 '@aws-sdk/types': 3.973.1 '@smithy/fetch-http-handler': 5.3.9 '@smithy/node-http-handler': 4.4.10 @@ -4857,16 +4854,16 @@ snapshots: '@smithy/util-stream': 4.5.12 tslib: 2.8.1 - '@aws-sdk/credential-provider-ini@3.972.7': + '@aws-sdk/credential-provider-ini@3.972.8': dependencies: - '@aws-sdk/core': 3.973.9 - '@aws-sdk/credential-provider-env': 3.972.7 - '@aws-sdk/credential-provider-http': 3.972.9 - '@aws-sdk/credential-provider-login': 3.972.7 - '@aws-sdk/credential-provider-process': 3.972.7 - '@aws-sdk/credential-provider-sso': 3.972.7 - '@aws-sdk/credential-provider-web-identity': 3.972.7 - '@aws-sdk/nested-clients': 3.989.0 + '@aws-sdk/core': 3.973.10 + '@aws-sdk/credential-provider-env': 3.972.8 + '@aws-sdk/credential-provider-http': 3.972.10 + '@aws-sdk/credential-provider-login': 3.972.8 + '@aws-sdk/credential-provider-process': 3.972.8 + '@aws-sdk/credential-provider-sso': 3.972.8 + '@aws-sdk/credential-provider-web-identity': 3.972.8 + '@aws-sdk/nested-clients': 3.990.0 '@aws-sdk/types': 3.973.1 '@smithy/credential-provider-imds': 4.2.8 '@smithy/property-provider': 4.2.8 @@ -4876,10 +4873,10 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-login@3.972.7': + '@aws-sdk/credential-provider-login@3.972.8': dependencies: - '@aws-sdk/core': 3.973.9 - '@aws-sdk/nested-clients': 3.989.0 + '@aws-sdk/core': 3.973.10 + '@aws-sdk/nested-clients': 3.990.0 '@aws-sdk/types': 3.973.1 '@smithy/property-provider': 4.2.8 '@smithy/protocol-http': 5.3.8 @@ -4889,14 +4886,14 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-node@3.972.8': + '@aws-sdk/credential-provider-node@3.972.9': dependencies: - '@aws-sdk/credential-provider-env': 3.972.7 - '@aws-sdk/credential-provider-http': 3.972.9 - '@aws-sdk/credential-provider-ini': 3.972.7 - '@aws-sdk/credential-provider-process': 3.972.7 - '@aws-sdk/credential-provider-sso': 3.972.7 - '@aws-sdk/credential-provider-web-identity': 3.972.7 + '@aws-sdk/credential-provider-env': 3.972.8 + '@aws-sdk/credential-provider-http': 3.972.10 + '@aws-sdk/credential-provider-ini': 3.972.8 + '@aws-sdk/credential-provider-process': 3.972.8 + '@aws-sdk/credential-provider-sso': 3.972.8 + '@aws-sdk/credential-provider-web-identity': 3.972.8 '@aws-sdk/types': 3.973.1 '@smithy/credential-provider-imds': 4.2.8 '@smithy/property-provider': 4.2.8 @@ -4906,20 +4903,20 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-process@3.972.7': + '@aws-sdk/credential-provider-process@3.972.8': dependencies: - '@aws-sdk/core': 3.973.9 + '@aws-sdk/core': 3.973.10 '@aws-sdk/types': 3.973.1 '@smithy/property-provider': 4.2.8 '@smithy/shared-ini-file-loader': 4.4.3 '@smithy/types': 4.12.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-sso@3.972.7': + '@aws-sdk/credential-provider-sso@3.972.8': dependencies: - '@aws-sdk/client-sso': 3.989.0 - '@aws-sdk/core': 3.973.9 - '@aws-sdk/token-providers': 3.989.0 + '@aws-sdk/client-sso': 3.990.0 + '@aws-sdk/core': 3.973.10 + '@aws-sdk/token-providers': 3.990.0 '@aws-sdk/types': 3.973.1 '@smithy/property-provider': 4.2.8 '@smithy/shared-ini-file-loader': 4.4.3 @@ -4928,10 +4925,10 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-web-identity@3.972.7': + '@aws-sdk/credential-provider-web-identity@3.972.8': dependencies: - '@aws-sdk/core': 3.973.9 - '@aws-sdk/nested-clients': 3.989.0 + '@aws-sdk/core': 3.973.10 + '@aws-sdk/nested-clients': 3.990.0 '@aws-sdk/types': 3.973.1 '@smithy/property-provider': 4.2.8 '@smithy/shared-ini-file-loader': 4.4.3 @@ -4957,12 +4954,12 @@ snapshots: '@smithy/types': 4.12.0 tslib: 2.8.1 - '@aws-sdk/middleware-flexible-checksums@3.972.7': + '@aws-sdk/middleware-flexible-checksums@3.972.8': dependencies: '@aws-crypto/crc32': 5.2.0 '@aws-crypto/crc32c': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/core': 3.973.9 + '@aws-sdk/core': 3.973.10 '@aws-sdk/crc64-nvme': 3.972.0 '@aws-sdk/types': 3.973.1 '@smithy/is-array-buffer': 4.2.0 @@ -5001,9 +4998,9 @@ snapshots: '@smithy/types': 4.12.0 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-s3@3.972.9': + '@aws-sdk/middleware-sdk-s3@3.972.10': dependencies: - '@aws-sdk/core': 3.973.9 + '@aws-sdk/core': 3.973.10 '@aws-sdk/types': 3.973.1 '@aws-sdk/util-arn-parser': 3.972.2 '@smithy/core': 3.23.0 @@ -5024,30 +5021,30 @@ snapshots: '@smithy/types': 4.12.0 tslib: 2.8.1 - '@aws-sdk/middleware-user-agent@3.972.9': + '@aws-sdk/middleware-user-agent@3.972.10': dependencies: - '@aws-sdk/core': 3.973.9 + '@aws-sdk/core': 3.973.10 '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-endpoints': 3.989.0 + '@aws-sdk/util-endpoints': 3.990.0 '@smithy/core': 3.23.0 '@smithy/protocol-http': 5.3.8 '@smithy/types': 4.12.0 tslib: 2.8.1 - '@aws-sdk/nested-clients@3.989.0': + '@aws-sdk/nested-clients@3.990.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.973.9 + '@aws-sdk/core': 3.973.10 '@aws-sdk/middleware-host-header': 3.972.3 '@aws-sdk/middleware-logger': 3.972.3 '@aws-sdk/middleware-recursion-detection': 3.972.3 - '@aws-sdk/middleware-user-agent': 3.972.9 + '@aws-sdk/middleware-user-agent': 3.972.10 '@aws-sdk/region-config-resolver': 3.972.3 '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-endpoints': 3.989.0 + '@aws-sdk/util-endpoints': 3.990.0 '@aws-sdk/util-user-agent-browser': 3.972.3 - '@aws-sdk/util-user-agent-node': 3.972.7 + '@aws-sdk/util-user-agent-node': 3.972.8 '@smithy/config-resolver': 4.4.6 '@smithy/core': 3.23.0 '@smithy/fetch-http-handler': 5.3.9 @@ -5085,19 +5082,19 @@ snapshots: '@smithy/types': 4.12.0 tslib: 2.8.1 - '@aws-sdk/signature-v4-multi-region@3.989.0': + '@aws-sdk/signature-v4-multi-region@3.990.0': dependencies: - '@aws-sdk/middleware-sdk-s3': 3.972.9 + '@aws-sdk/middleware-sdk-s3': 3.972.10 '@aws-sdk/types': 3.973.1 '@smithy/protocol-http': 5.3.8 '@smithy/signature-v4': 5.3.8 '@smithy/types': 4.12.0 tslib: 2.8.1 - '@aws-sdk/token-providers@3.989.0': + '@aws-sdk/token-providers@3.990.0': dependencies: - '@aws-sdk/core': 3.973.9 - '@aws-sdk/nested-clients': 3.989.0 + '@aws-sdk/core': 3.973.10 + '@aws-sdk/nested-clients': 3.990.0 '@aws-sdk/types': 3.973.1 '@smithy/property-provider': 4.2.8 '@smithy/shared-ini-file-loader': 4.4.3 @@ -5115,7 +5112,7 @@ snapshots: dependencies: tslib: 2.8.1 - '@aws-sdk/util-endpoints@3.989.0': + '@aws-sdk/util-endpoints@3.990.0': dependencies: '@aws-sdk/types': 3.973.1 '@smithy/types': 4.12.0 @@ -5131,12 +5128,12 @@ snapshots: dependencies: '@aws-sdk/types': 3.973.1 '@smithy/types': 4.12.0 - bowser: 2.13.1 + bowser: 2.14.1 tslib: 2.8.1 - '@aws-sdk/util-user-agent-node@3.972.7': + '@aws-sdk/util-user-agent-node@3.972.8': dependencies: - '@aws-sdk/middleware-user-agent': 3.972.9 + '@aws-sdk/middleware-user-agent': 3.972.10 '@aws-sdk/types': 3.973.1 '@smithy/node-config-provider': 4.3.8 '@smithy/types': 4.12.0 @@ -5909,8 +5906,6 @@ snapshots: '@rspack/lite-tapable@1.1.0': {} - '@standard-schema/spec@1.1.0': {} - '@smithy/abort-controller@4.2.8': dependencies: '@smithy/types': 4.12.0 @@ -6249,6 +6244,8 @@ snapshots: dependencies: tslib: 2.8.1 + '@standard-schema/spec@1.1.0': {} + '@swc/helpers@0.5.17': dependencies: tslib: 2.8.1 @@ -7061,7 +7058,7 @@ snapshots: fast-deep-equal: 3.1.3 multicast-dns: 7.2.5 - bowser@2.13.1: {} + bowser@2.14.1: {} brace-expansion@1.1.12: dependencies: @@ -7793,11 +7790,11 @@ snapshots: fast-uri@3.0.3: {} - fast-xml-parser@5.3.5: + fast-xml-parser@5.3.4: dependencies: strnum: 2.1.2 - fast-xml-parser@5.3.4: + fast-xml-parser@5.3.5: dependencies: strnum: 2.1.2 @@ -9318,8 +9315,6 @@ snapshots: strnum@2.1.2: {} - strnum@2.1.2: {} - supports-color@7.2.0: dependencies: has-flag: 4.0.0 From abe3f4d8ca58f8650c18b9c7652d641236779633 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E4=B8=80=E4=B9=8B?= Date: Sun, 15 Feb 2026 21:33:33 +0800 Subject: [PATCH 12/15] =?UTF-8?q?=E9=87=8D=E6=9E=84s3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 - packages/filesystem/s3/client.ts | 341 +++++++++ packages/filesystem/s3/rw.ts | 76 +- packages/filesystem/s3/s3.ts | 291 +++---- pnpm-lock.yaml | 1233 +----------------------------- 5 files changed, 530 insertions(+), 1412 deletions(-) create mode 100644 packages/filesystem/s3/client.ts diff --git a/package.json b/package.json index bfe510f77..fa7228c66 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,6 @@ }, "dependencies": { "@arco-design/web-react": "^2.66.7", - "@aws-sdk/client-s3": "^3.989.0", "@dnd-kit/core": "^6.3.1", "@dnd-kit/modifiers": "^9.0.0", "@dnd-kit/sortable": "^10.0.0", diff --git a/packages/filesystem/s3/client.ts b/packages/filesystem/s3/client.ts new file mode 100644 index 000000000..3180cb4f1 --- /dev/null +++ b/packages/filesystem/s3/client.ts @@ -0,0 +1,341 @@ +/** + * 轻量级 Amazon S3 HTTP 客户端 + * 使用 AWS Signature V4 签名,通过原生 fetch 发送请求 + * 不依赖 @aws-sdk/client-s3 + */ + +export interface S3ClientConfig { + region: string; + credentials: { + accessKeyId: string; + secretAccessKey: string; + }; + endpoint?: string; + /** 强制路径式访问(默认 true,兼容 MinIO 等) */ + forcePathStyle?: boolean; +} + +// ---- 加密工具函数 (使用 Web Crypto API) ---- + +async function sha256(data: string | Uint8Array): Promise { + const encoded = typeof data === "string" ? new TextEncoder().encode(data) : data; + return crypto.subtle.digest("SHA-256", encoded.buffer as ArrayBuffer); +} + +function toHex(buffer: ArrayBuffer): string { + return Array.from(new Uint8Array(buffer)) + .map((b) => b.toString(16).padStart(2, "0")) + .join(""); +} + +async function sha256Hex(data: string | Uint8Array): Promise { + return toHex(await sha256(data)); +} + +async function hmacSha256(key: ArrayBuffer, data: string): Promise { + const cryptoKey = await crypto.subtle.importKey("raw", key, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]); + const encoded = new TextEncoder().encode(data); + return crypto.subtle.sign("HMAC", cryptoKey, encoded.buffer as ArrayBuffer); +} + +/** 派生 AWS Signature V4 签名密钥 */ +async function deriveSigningKey( + secretKey: string, + dateStamp: string, + region: string, + service: string +): Promise { + const kDate = await hmacSha256(new TextEncoder().encode(`AWS4${secretKey}`).buffer as ArrayBuffer, dateStamp); + const kRegion = await hmacSha256(kDate, region); + const kService = await hmacSha256(kRegion, service); + return hmacSha256(kService, "aws4_request"); +} + +// ---- URI 编码 ---- + +/** AWS Signature V4 要求的 URI 编码,仅保留 A-Za-z0-9_-.~ 不编码 */ +function awsUriEncode(str: string, encodeSlash: boolean = true): string { + let result = ""; + const bytes = new TextEncoder().encode(str); + for (const b of bytes) { + const ch = String.fromCharCode(b); + if ( + (ch >= "A" && ch <= "Z") || + (ch >= "a" && ch <= "z") || + (ch >= "0" && ch <= "9") || + ch === "_" || + ch === "-" || + ch === "~" || + ch === "." + ) { + result += ch; + } else if (ch === "/" && !encodeSlash) { + result += ch; + } else { + result += `%${b.toString(16).toUpperCase().padStart(2, "0")}`; + } + } + return result; +} + +// ---- S3 错误处理 ---- + +/** S3 服务端返回的错误 */ +export class S3Error extends Error { + code: string; + statusCode: number; + + constructor(code: string, message: string, statusCode: number) { + super(message); + this.name = code; // 兼容原 SDK 行为 (error.name === "NotFound" 等) + this.code = code; + this.statusCode = statusCode; + } +} + +/** 从 S3 响应解析错误信息 */ +async function parseS3Error(response: Response): Promise { + // 状态码到错误名称的映射(用于 HEAD 等无响应体的请求) + const statusCodeMap: Record = { + 301: "PermanentRedirect", + 400: "BadRequest", + 403: "AccessDenied", + 404: "NotFound", + 409: "Conflict", + }; + + try { + const text = await response.text(); + if (text) { + const codeMatch = text.match(/(.*?)<\/Code>/); + const messageMatch = text.match(/(.*?)<\/Message>/); + if (codeMatch) { + return new S3Error(codeMatch[1], messageMatch?.[1] || response.statusText, response.status); + } + } + } catch { + // 解析失败则使用状态码映射 + } + + const code = statusCodeMap[response.status] || `HTTP${response.status}`; + return new S3Error(code, response.statusText, response.status); +} + +// ---- S3 客户端 ---- + +export class S3Client { + private config: Required>; + private parsedEndpoint: URL; + private customEndpoint: boolean; + + constructor(config: S3ClientConfig) { + this.config = { + region: config.region || "us-east-1", + credentials: config.credentials, + forcePathStyle: config.forcePathStyle ?? true, + }; + this.customEndpoint = !!config.endpoint; + + let endpoint: string; + if (config.endpoint) { + endpoint = config.endpoint.trim(); + if (!endpoint.startsWith("http://") && !endpoint.startsWith("https://")) { + endpoint = `https://${endpoint}`; + } + } else { + endpoint = `https://s3.${this.config.region}.amazonaws.com`; + } + // 去除尾部斜杠 + endpoint = endpoint.replace(/\/+$/, ""); + this.parsedEndpoint = new URL(endpoint); + } + + /** 获取请求的 Host */ + private getHost(bucket: string): string { + const { hostname, port } = this.parsedEndpoint; + const hostWithPort = port ? `${hostname}:${port}` : hostname; + if (this.config.forcePathStyle) { + return hostWithPort; + } + return `${bucket}.${hostWithPort}`; + } + + /** 获取签名用的 Canonical URI */ + private getCanonicalUri(bucket: string, key?: string): string { + if (this.config.forcePathStyle) { + let uri = `/${awsUriEncode(bucket)}`; + if (key) uri += `/${awsUriEncode(key, false)}`; + return uri; + } + if (key) return `/${awsUriEncode(key, false)}`; + return "/"; + } + + /** 构建请求 URL */ + private buildUrl(bucket: string, key?: string, queryParams?: Record): string { + const proto = this.parsedEndpoint.protocol; + const host = this.getHost(bucket); + let path: string; + if (this.config.forcePathStyle) { + path = `/${bucket}`; + if (key) path += `/${awsUriEncode(key, false)}`; + } else { + path = key ? `/${awsUriEncode(key, false)}` : "/"; + } + + let url = `${proto}//${host}${path}`; + if (queryParams && Object.keys(queryParams).length > 0) { + const qs = Object.entries(queryParams) + .sort(([a], [b]) => a.localeCompare(b)) + .map(([k, v]) => `${awsUriEncode(k)}=${awsUriEncode(v)}`) + .join("&"); + url += `?${qs}`; + } + return url; + } + + /** AWS Signature V4 签名 */ + private async signRequest( + method: string, + bucket: string, + key: string | undefined, + queryParams: Record, + headers: Record, + payloadHash: string + ): Promise { + const now = new Date(); + // ISO 8601 基本格式: 20210101T000000Z + const amzDate = now + .toISOString() + .replace(/[-:]/g, "") + .replace(/\.\d{3}/, ""); + const dateStamp = amzDate.substring(0, 8); + + headers["host"] = this.getHost(bucket); + headers["x-amz-date"] = amzDate; + headers["x-amz-content-sha256"] = payloadHash; + + // 构建 Canonical Request + const canonicalUri = this.getCanonicalUri(bucket, key); + const canonicalQueryString = Object.entries(queryParams) + .sort(([a], [b]) => a.localeCompare(b)) + .map(([k, v]) => `${awsUriEncode(k)}=${awsUriEncode(v)}`) + .join("&"); + + const signedHeaderKeys = Object.keys(headers) + .map((k) => k.toLowerCase()) + .sort(); + const canonicalHeaders = signedHeaderKeys.map((k) => `${k}:${(headers[k] ?? "").trim()}\n`).join(""); + const signedHeaders = signedHeaderKeys.join(";"); + + const canonicalRequest = [ + method, + canonicalUri, + canonicalQueryString, + canonicalHeaders, + signedHeaders, + payloadHash, + ].join("\n"); + + // 构建 String to Sign + const credentialScope = `${dateStamp}/${this.config.region}/s3/aws4_request`; + const canonicalRequestHash = await sha256Hex(canonicalRequest); + const stringToSign = ["AWS4-HMAC-SHA256", amzDate, credentialScope, canonicalRequestHash].join("\n"); + + // 计算签名 + const signingKey = await deriveSigningKey( + this.config.credentials.secretAccessKey, + dateStamp, + this.config.region, + "s3" + ); + const signature = toHex(await hmacSha256(signingKey, stringToSign)); + + // 添加 Authorization 头 + headers["authorization"] = + `AWS4-HMAC-SHA256 Credential=${this.config.credentials.accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`; + } + + /** + * 发送 S3 请求 + * @param method HTTP 方法 + * @param bucket Bucket 名称 + * @param key 对象 Key(可选) + * @param options 请求选项 + * @returns 成功时返回 Response + * @throws {S3Error} S3 服务端错误 + */ + async request( + method: string, + bucket: string, + key?: string, + options?: { + queryParams?: Record; + body?: string | Uint8Array; + headers?: Record; + } + ): Promise { + const queryParams = options?.queryParams || {}; + // 规范化 headers(全部小写 key) + const headers: Record = {}; + if (options?.headers) { + for (const [k, v] of Object.entries(options.headers)) { + headers[k.toLowerCase()] = v; + } + } + + // 计算 payload SHA-256 + let payloadHash: string; + if (options?.body) { + const bodyBytes = typeof options.body === "string" ? new TextEncoder().encode(options.body) : options.body; + payloadHash = await sha256Hex(bodyBytes); + } else { + payloadHash = await sha256Hex(""); + } + + // 签名 + await this.signRequest(method, bucket, key, queryParams, headers, payloadHash); + + // 发送请求(移除 host 头,fetch 会自动设置) + const url = this.buildUrl(bucket, key, queryParams); + const fetchHeaders = { ...headers }; + delete fetchHeaders["host"]; + + const response = await fetch(url, { + method, + headers: fetchHeaders, + body: options?.body + ? options.body instanceof Uint8Array + ? (options.body.buffer as ArrayBuffer) + : options.body + : undefined, + }); + + // 非 2xx 响应视为错误 + if (!response.ok) { + throw await parseS3Error(response); + } + + return response; + } + + /** 获取 endpoint URL */ + getEndpointUrl(): string { + return this.parsedEndpoint.origin; + } + + /** 是否使用了自定义 endpoint */ + hasCustomEndpoint(): boolean { + return this.customEndpoint; + } + + /** 获取 region */ + getRegion(): string { + return this.config.region; + } + + /** 获取 forcePathStyle */ + isForcePathStyle(): boolean { + return this.config.forcePathStyle; + } +} diff --git a/packages/filesystem/s3/rw.ts b/packages/filesystem/s3/rw.ts index f6e95689b..fff7ee4e2 100644 --- a/packages/filesystem/s3/rw.ts +++ b/packages/filesystem/s3/rw.ts @@ -1,10 +1,9 @@ -import { GetObjectCommand, PutObjectCommand } from "@aws-sdk/client-s3"; -import type { S3Client } from "@aws-sdk/client-s3"; +import type { S3Client } from "./client"; import type { FileReader, FileWriter } from "../filesystem"; /** - * FileReader implementation for Amazon S3. - * Downloads and reads file content from S3. + * S3 文件读取器 + * 通过 GET 请求下载 S3 对象 */ export class S3FileReader implements FileReader { client: S3Client; @@ -20,46 +19,23 @@ export class S3FileReader implements FileReader { } /** - * Reads file content from S3. - * @param type - Output format: "string" for text, "blob" for binary (default) - * @returns File content as string or Blob - * @throws {Error} If file not found or read fails + * 读取文件内容 + * @param type 输出格式:"string" 为文本,"blob" 为二进制(默认) + * @returns 文件内容 + * @throws {S3Error} 文件不存在或读取失败 */ async read(type: "string" | "blob" = "blob"): Promise { - try { - const command = new GetObjectCommand({ - Bucket: this.bucket, - Key: this.key, - }); - - const response = await this.client.send(command); - - if (!response.Body) { - throw new Error("Empty response body from S3"); - } - - if (type === "string") { - // Built-in v3 helper - const text = await response.Body.transformToString(); - return text; - } else { - // Or transformToByteArray() - const stream = response.Body.transformToWebStream(); - const blob = await new Response(stream).blob(); - return blob; - } - } catch (error: any) { - if (error.name === "NoSuchKey") { - throw new Error(`File not found: ${this.key}`); - } - throw error; + const response = await this.client.request("GET", this.bucket, this.key); + if (type === "string") { + return response.text(); } + return response.blob(); } } /** - * FileWriter implementation for Amazon S3. - * Uploads file content to S3 with optional metadata. + * S3 文件写入器 + * 通过 PUT 请求上传内容到 S3 */ export class S3FileWriter implements FileWriter { client: S3Client; @@ -78,24 +54,24 @@ export class S3FileWriter implements FileWriter { } /** - * Writes content to S3. - * @param content - File content as string or Blob - * @throws {Error} If upload fails + * 写入文件内容 + * @param content 文件内容(字符串或 Blob) + * @throws {S3Error} 上传失败 */ async write(content: string | Blob): Promise { - const metadata: Record = {}; + const body = content instanceof Blob ? new Uint8Array(await content.arrayBuffer()) : content; + + const headers: Record = { + "content-type": "application/octet-stream", + }; if (this.modifiedDate) { - // 用 ISO 8601 格式 - metadata.createtime = new Date(this.modifiedDate).toISOString(); // 规范格式 + // 通过自定义元数据保存创建时间(ISO 8601 格式) + headers["x-amz-meta-createtime"] = new Date(this.modifiedDate).toISOString(); } - const command = new PutObjectCommand({ - Bucket: this.bucket, - Key: this.key, - Body: content, // API 的 Body 接受 string | Blob | Uint8Array | Buffer | Readable | ReadableStream - Metadata: Object.keys(metadata).length > 0 ? metadata : undefined, + await this.client.request("PUT", this.bucket, this.key, { + body: typeof body === "string" ? body : body, + headers, }); - - await this.client.send(command); } } diff --git a/packages/filesystem/s3/s3.ts b/packages/filesystem/s3/s3.ts index 263a0ef5a..b03cc23c6 100644 --- a/packages/filesystem/s3/s3.ts +++ b/packages/filesystem/s3/s3.ts @@ -1,71 +1,102 @@ -import { - S3Client, - HeadBucketCommand, - ListObjectsV2Command, - DeleteObjectCommand, - type S3ClientConfig, -} from "@aws-sdk/client-s3"; +import { S3Client, S3Error } from "./client"; +import type { S3ClientConfig } from "./client"; import type FileSystem from "../filesystem"; import type { FileInfo, FileCreateOptions, FileReader, FileWriter } from "../filesystem"; import { joinPath } from "../utils"; import { S3FileReader, S3FileWriter } from "./rw"; import { WarpTokenError } from "../error"; +// ---- ListObjectsV2 XML 解析 ---- + +interface ListObjectsV2Result { + contents: Array<{ + key: string; + lastModified: string; + etag: string; + size: number; + }>; + isTruncated: boolean; + nextContinuationToken?: string; +} + +/** 从 ListObjectsV2 XML 响应中解析对象列表 */ +function parseListObjectsV2(xml: string): ListObjectsV2Result { + const contents: ListObjectsV2Result["contents"] = []; + const contentsRegex = /([\s\S]*?)<\/Contents>/g; + let match; + while ((match = contentsRegex.exec(xml)) !== null) { + const block = match[1]; + const key = block.match(/([\s\S]*?)<\/Key>/)?.[1] || ""; + const lastModified = block.match(/([\s\S]*?)<\/LastModified>/)?.[1] || ""; + const etag = block.match(/([\s\S]*?)<\/ETag>/)?.[1] || ""; + const size = parseInt(block.match(/([\s\S]*?)<\/Size>/)?.[1] || "0", 10); + contents.push({ key, lastModified, etag, size }); + } + + const isTruncated = /true<\/IsTruncated>/.test(xml); + const nextToken = xml.match(/([\s\S]*?)<\/NextContinuationToken>/)?.[1]; + + return { contents, isTruncated, nextContinuationToken: nextToken }; +} + +// ---- S3 文件系统 ---- + /** - * Amazon S3 implementation of the FileSystem interface. - * Supports AWS S3 and S3-compatible services (MinIO, Wasabi, etc.). + * Amazon S3 文件系统实现 + * 支持 AWS S3 及兼容服务(MinIO、Wasabi 等) + * 使用原生 fetch + AWS Signature V4 签名,不依赖 @aws-sdk/client-s3 */ export default class S3FileSystem implements FileSystem { client: S3Client; bucket: string; - region: string; + region: string = ""; basePath: string = "/"; - /** - * Creates a new S3FileSystem instance. - * - * @param bucket - S3 bucket name - * @param region - AWS region (e.g., "us-east-1") - * @param accessKeyId - AWS access key ID - * @param secretAccessKey - AWS secret access key - * @param endpoint - Optional custom endpoint for S3-compatible services - * @param basePath - Optional base path for directory scoping - */ + constructor(bucket: string, client: S3Client, basePath?: string); constructor( bucket: string, region: string, accessKeyId: string, secretAccessKey: string, endpoint?: string, - basePath?: string, - usePathStyle: boolean = true // 默认兼容S3 + basePath?: string + ); + constructor( + bucket: string, + regionOrClient: string | S3Client, + accessKeyIdOrBasePath?: string, + secretAccessKey?: string, + endpoint?: string, + basePath?: string ) { this.bucket = bucket; - this.region = region; + if (regionOrClient instanceof S3Client) { + this.client = regionOrClient; + this.basePath = accessKeyIdOrBasePath || "/"; + return; + } + this.region = regionOrClient || "us-east-1"; this.basePath = basePath || "/"; const config: S3ClientConfig = { - region, + region: this.region, credentials: { - accessKeyId, - secretAccessKey, + accessKeyId: accessKeyIdOrBasePath!, + secretAccessKey: secretAccessKey!, }, - // forcePathStyle: true 对 AWS 官方 S3 不是最佳实践(会用 path-style URL,已被逐渐弃用),对 MinIO 等兼容服务则是必须的。硬编码会导致部分用户配置失败。 - forcePathStyle: usePathStyle, + forcePathStyle: true, // 强制路径式访问,兼容大多数 S3 服务 }; if (endpoint) { - // AWS SDK v3 要求 endpoint 是完整 URL(带 https://)。缺少协议会导致 InvalidEndpoint 或连接失败。 - // 自动补全协议(常见兼容做法) let fixedEndpoint = `${endpoint}`.trim(); if (!fixedEndpoint.startsWith("http://") && !fixedEndpoint.startsWith("https://")) { fixedEndpoint = `https://${fixedEndpoint}`; } config.endpoint = fixedEndpoint; - // 自动检测:如果 endpoint 包含 amazonaws.com,设为 false。 + // amazonaws.com 域名使用虚拟主机风格 if (endpoint.includes("amazonaws.com")) config.forcePathStyle = false; } @@ -73,112 +104,88 @@ export default class S3FileSystem implements FileSystem { } /** - * Verifies bucket access and credentials. - * @throws {WarpTokenError} If authentication fails - * @throws {Error} If bucket not found or network error + * 验证 Bucket 访问权限和凭证 + * @throws {WarpTokenError} 认证失败 + * @throws {Error} Bucket 不存在或网络错误 */ async verify(): Promise { try { - const command = new HeadBucketCommand({ - Bucket: this.bucket, - }); - await this.client.send(command); + await this.client.request("HEAD", this.bucket); } catch (error: any) { - if (error.name === "NotFound") { - throw new Error("NotFound"); // Bucket 不存在 - } - if ( - error.name === "InvalidAccessKeyId" || - error.name === "SignatureDoesNotMatch" || - error.name === "InvalidClientTokenId" - ) { - throw new WarpTokenError(error); // AccessKey 或 SecretKey 无效 - } - if (error.name === "AccessDenied") { - throw new Error("Access Denied"); // 无权限访问该 Bucket(Access Denied) - } - if (error.name === "PermanentRedirect") { - throw new Error("Access Denied"); // Region 设置错误,请检查 region 是否匹配 Bucket 所在区域 - } - if (error.name === "NoSuchBucket") { - throw new Error(`Bucket not found: ${this.bucket}`); + if (error instanceof S3Error) { + if (error.code === "NotFound" || error.code === "NoSuchBucket" || error.statusCode === 404) { + throw new Error("NotFound"); + } + if ( + error.code === "InvalidAccessKeyId" || + error.code === "SignatureDoesNotMatch" || + error.code === "InvalidClientTokenId" + ) { + throw new WarpTokenError(error); + } + if ( + error.code === "AccessDenied" || + error.code === "PermanentRedirect" || + error.statusCode === 403 || + error.statusCode === 301 + ) { + throw new Error("Access Denied"); + } } if (error.message?.includes("getaddrinfo") || error.message?.includes("fetch failed")) { - throw new Error("Network connection failed. Please check your internet connection."); // 网络连接失败,请检查 endpoint 或网络 + throw new Error("Network connection failed. Please check your internet connection."); } throw error; } } /** - * Opens a file for reading. - * @param file - File information - * @returns FileReader instance for reading file content + * 打开文件用于读取 + * @param file 文件信息 + * @returns 文件读取器 */ async open(file: FileInfo): Promise { - const key = joinPath(file.path, file.name).substring(1); // Remove leading / + const key = joinPath(file.path, file.name).substring(1); // 去除前导 / return new S3FileReader(this.client, this.bucket, key); } /** - * Opens a directory (returns a new FileSystem scoped to that directory). - * @param path - Directory path relative to current basePath - * @returns New S3FileSystem instance scoped to the directory + * 打开子目录(返回新的 S3FileSystem 实例) + * @param path 相对于当前 basePath 的目录路径 + * @returns 新的 S3FileSystem 实例 */ async openDir(path: string): Promise { - const newBasePath = joinPath(this.basePath, path); - const fs = new S3FileSystem( - this.bucket, - this.region, - "", // 占位: These won't be used since we're reusing the client - "", - undefined, - newBasePath, - true // forcePathStyle 同父 - ); - // openDir 又 new 一个 S3FileSystem,但传了空字符串的 AK/SK,导致逻辑不清晰。 - // 复用原有 client,只修改 basePath。 - fs.client = this.client; // 复用 client - return fs; + return new S3FileSystem(this.bucket, this.client, joinPath(this.basePath, path)); } /** - * Creates a file for writing. - * @param path - File path relative to current basePath - * @param opts - Optional file creation options (modifiedDate) - * @returns FileWriter instance for writing file content + * 创建文件用于写入 + * @param path 相对于当前 basePath 的文件路径 + * @param opts 可选的文件创建选项 + * @returns 文件写入器 */ async create(path: string, opts?: FileCreateOptions): Promise { - const key = joinPath(this.basePath, path).substring(1); // Remove leading / - return new S3FileWriter(this.client, this.bucket, key, opts?.modifiedDate); + return new S3FileWriter(this.client, this.bucket, joinPath(this.basePath, path).substring(1), opts?.modifiedDate); } /** - * Creates a directory (no-op for S3, directories are implicit). - * @param _path - Directory path (unused) - * @param _opts - Optional creation options (unused) + * 创建目录(S3 中目录是隐式的,无需操作) */ async createDir(_path: string, _opts?: FileCreateOptions): Promise { - // No-op: S3 doesn't require explicit directory creation return Promise.resolve(); } /** - * Deletes a file from S3. - * This operation is idempotent - deleting a non-existent file succeeds. - * @param path - File path relative to current basePath + * 删除文件 + * 此操作幂等——删除不存在的文件也会成功 + * @param path 相对于当前 basePath 的文件路径 */ async delete(path: string): Promise { try { - const key = joinPath(this.basePath, path).substring(1); // Remove leading / - const command = new DeleteObjectCommand({ - Bucket: this.bucket, - Key: key, - }); - await this.client.send(command); + await this.client.request("DELETE", this.bucket, joinPath(this.basePath, path).substring(1)); } catch (error: any) { - // S3 delete is idempotent - if the key doesn't exist, it succeeds - if (error.name === "NoSuchKey") { + // S3 delete 是幂等的,key 不存在时也视为成功 + if (error instanceof S3Error && error.code === "NoSuchKey") { return; } throw error; @@ -186,61 +193,54 @@ export default class S3FileSystem implements FileSystem { } /** - * Lists files in the current directory. - * Handles pagination automatically for large directories. - * @returns Array of FileInfo objects for files in current directory - * @throws {Error} If permission denied or other S3 error + * 列出当前目录下的文件 + * 自动处理分页 + * @returns 文件信息数组 */ async list(): Promise { - const prefix = this.basePath === "/" ? "" : this.basePath.substring(1); + let prefix = this.basePath === "/" ? "" : this.basePath.substring(1); + // 确保 prefix 以 / 结尾(除了根目录),这样才能正确列出目录下的文件 + if (prefix && !prefix.endsWith("/")) { + prefix += "/"; + } const files: FileInfo[] = []; let continuationToken: string | undefined; try { do { - const command = new ListObjectsV2Command({ - Bucket: this.bucket, - Prefix: prefix, - Delimiter: "/", - ContinuationToken: continuationToken, - MaxKeys: 1000, // ← 每次最多 1000,防滥用 - }); - - const response = await this.client.send(command); + const queryParams: Record = { + "list-type": "2", + delimiter: "/", + "max-keys": "1000", + }; + if (prefix) queryParams["prefix"] = prefix; + if (continuationToken) queryParams["continuation-token"] = continuationToken; - // 处理 CommonPrefixes(子目录) - // if (response.CommonPrefixes) { - // for (const prefix of response.CommonPrefixes) { - // if (prefix.Prefix && prefix.Prefix !== this.basePath) { - // } - // } - // } + const response = await this.client.request("GET", this.bucket, undefined, { queryParams }); + const xml = await response.text(); + const result = parseListObjectsV2(xml); - // 处理 Contents(文件) - if (response.Contents) { - for (const obj of response.Contents) { - if (!obj.Key) continue; - if (obj.Key && obj.Key.endsWith("/")) continue; // 跳过目录占位符 - if (obj.Key === this.basePath.slice(1)) continue; // 跳过 prefix 本身 + for (const obj of result.contents) { + if (!obj.key) continue; + if (obj.key.endsWith("/")) continue; // 跳过目录占位符 + if (prefix && obj.key === prefix) continue; // 跳过 prefix 本身 - // const name = obj.Key.substring(prefix.length); - const relativeKey = obj.Key.slice(this.basePath.length); - if (!relativeKey) continue; + const relativeKey = prefix ? obj.key.slice(prefix.length) : obj.key; + if (!relativeKey) continue; - const lastModified = obj.LastModified?.getTime() || Date.now(); + const lastModified = new Date(obj.lastModified).getTime() || Date.now(); - files.push({ - name: relativeKey, - path: this.basePath, - size: obj.Size || 0, - digest: obj.ETag?.replace(/"/g, "") || "", - createtime: lastModified, - updatetime: lastModified, - }); - } + files.push({ + name: relativeKey, + path: this.basePath, + size: obj.size || 0, + digest: obj.etag?.replace(/"/g, "") || "", + createtime: lastModified, + updatetime: lastModified, + }); } - continuationToken = response.NextContinuationToken; + continuationToken = result.nextContinuationToken; } while (continuationToken); if (files.length > 10000) { @@ -249,7 +249,7 @@ export default class S3FileSystem implements FileSystem { return files; } catch (error: any) { - if (error.name === "AccessDenied") { + if (error instanceof S3Error && error.code === "AccessDenied") { throw new Error(`Permission denied. Check your IAM permissions for bucket: ${this.bucket}`); } throw error; @@ -257,11 +257,16 @@ export default class S3FileSystem implements FileSystem { } /** - * Gets the S3 console URL for the current directory. - * @returns URL to S3 console for this bucket/prefix + * 获取当前目录的 URL + * 自定义 endpoint 返回 endpoint + bucket/prefix 路径 + * AWS S3 返回控制台 URL */ async getDirUrl(): Promise { const prefix = this.basePath === "/" ? "" : this.basePath.substring(1); + if (this.client.hasCustomEndpoint()) { + const url = this.client.getEndpointUrl(); + return `${url}/${this.bucket}/${prefix}`; + } return `https://s3.console.aws.amazon.com/s3/buckets/${this.bucket}?prefix=${encodeURIComponent(prefix)}®ion=${this.region}`; } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b26d7c286..c530ea985 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,9 +11,6 @@ importers: '@arco-design/web-react': specifier: ^2.66.7 version: 2.66.7(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@aws-sdk/client-s3': - specifier: ^3.989.0 - version: 3.990.0 '@dnd-kit/core': specifier: ^6.3.1 version: 6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -228,169 +225,6 @@ packages: '@asamuzakjp/css-color@3.2.0': resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} - '@aws-crypto/crc32@5.2.0': - resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} - engines: {node: '>=16.0.0'} - - '@aws-crypto/crc32c@5.2.0': - resolution: {integrity: sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==} - - '@aws-crypto/sha1-browser@5.2.0': - resolution: {integrity: sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==} - - '@aws-crypto/sha256-browser@5.2.0': - resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} - - '@aws-crypto/sha256-js@5.2.0': - resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} - engines: {node: '>=16.0.0'} - - '@aws-crypto/supports-web-crypto@5.2.0': - resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} - - '@aws-crypto/util@5.2.0': - resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} - - '@aws-sdk/client-s3@3.990.0': - resolution: {integrity: sha512-XnsM8RgB35Atn2+aYSocitCybDG82x9yYf/s2D23ytpyHCupmuZN3LzK2a0WxmKO6Zf7EtEIYy0mHGY4tLp9YA==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/client-sso@3.990.0': - resolution: {integrity: sha512-xTEaPjZwOqVjGbLOP7qzwbdOWJOo1ne2mUhTZwEBBkPvNk4aXB/vcYwWwrjoSWUqtit4+GDbO75ePc/S6TUJYQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/core@3.973.10': - resolution: {integrity: sha512-4u/FbyyT3JqzfsESI70iFg6e2yp87MB5kS2qcxIA66m52VSTN1fvuvbCY1h/LKq1LvuxIrlJ1ItcyjvcKoaPLg==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/crc64-nvme@3.972.0': - resolution: {integrity: sha512-ThlLhTqX68jvoIVv+pryOdb5coP1cX1/MaTbB9xkGDCbWbsqQcLqzPxuSoW1DCnAAIacmXCWpzUNOB9pv+xXQw==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-env@3.972.8': - resolution: {integrity: sha512-r91OOPAcHnLCSxaeu/lzZAVRCZ/CtTNuwmJkUwpwSDshUrP7bkX1OmFn2nUMWd9kN53Q4cEo8b7226G4olt2Mg==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-http@3.972.10': - resolution: {integrity: sha512-DTtuyXSWB+KetzLcWaSahLJCtTUe/3SXtlGp4ik9PCe9xD6swHEkG8n8/BNsQ9dsihb9nhFvuUB4DpdBGDcvVg==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-ini@3.972.8': - resolution: {integrity: sha512-n2dMn21gvbBIEh00E8Nb+j01U/9rSqFIamWRdGm/mE5e+vHQ9g0cBNdrYFlM6AAiryKVHZmShWT9D1JAWJ3ISw==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-login@3.972.8': - resolution: {integrity: sha512-rMFuVids8ICge/X9DF5pRdGMIvkVhDV9IQFQ8aTYk6iF0rl9jOUa1C3kjepxiXUlpgJQT++sLZkT9n0TMLHhQw==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-node@3.972.9': - resolution: {integrity: sha512-LfJfO0ClRAq2WsSnA9JuUsNyIicD2eyputxSlSL0EiMrtxOxELLRG6ZVYDf/a1HCepaYPXeakH4y8D5OLCauag==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-process@3.972.8': - resolution: {integrity: sha512-6cg26ffFltxM51OOS8NH7oE41EccaYiNlbd5VgUYwhiGCySLfHoGuGrLm2rMB4zhy+IO5nWIIG0HiodX8zdvHA==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-sso@3.972.8': - resolution: {integrity: sha512-35kqmFOVU1n26SNv+U37sM8b2TzG8LyqAcd6iM9gprqxyHEh/8IM3gzN4Jzufs3qM6IrH8e43ryZWYdvfVzzKQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/credential-provider-web-identity@3.972.8': - resolution: {integrity: sha512-CZhN1bOc1J3ubQPqbmr5b4KaMJBgdDvYsmEIZuX++wFlzmZsKj1bwkaiTEb5U2V7kXuzLlpF5HJSOM9eY/6nGA==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/middleware-bucket-endpoint@3.972.3': - resolution: {integrity: sha512-fmbgWYirF67YF1GfD7cg5N6HHQ96EyRNx/rDIrTF277/zTWVuPI2qS/ZHgofwR1NZPe/NWvoppflQY01LrbVLg==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/middleware-expect-continue@3.972.3': - resolution: {integrity: sha512-4msC33RZsXQpUKR5QR4HnvBSNCPLGHmB55oDiROqqgyOc+TOfVu2xgi5goA7ms6MdZLeEh2905UfWMnMMF4mRg==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/middleware-flexible-checksums@3.972.8': - resolution: {integrity: sha512-Hn6gumcN/3/8Fzo9z7N1pA2PRfE8S+qAqdb4g3MqzXjIOIe+VxD7edO/DKAJ1YH11639EGQIHBz0wdOb5btjtw==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/middleware-host-header@3.972.3': - resolution: {integrity: sha512-aknPTb2M+G3s+0qLCx4Li/qGZH8IIYjugHMv15JTYMe6mgZO8VBpYgeGYsNMGCqCZOcWzuf900jFBG5bopfzmA==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/middleware-location-constraint@3.972.3': - resolution: {integrity: sha512-nIg64CVrsXp67vbK0U1/Is8rik3huS3QkRHn2DRDx4NldrEFMgdkZGI/+cZMKD9k4YOS110Dfu21KZLHrFA/1g==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/middleware-logger@3.972.3': - resolution: {integrity: sha512-Ftg09xNNRqaz9QNzlfdQWfpqMCJbsQdnZVJP55jfhbKi1+FTWxGuvfPoBhDHIovqWKjqbuiew3HuhxbJ0+OjgA==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/middleware-recursion-detection@3.972.3': - resolution: {integrity: sha512-PY57QhzNuXHnwbJgbWYTrqIDHYSeOlhfYERTAuc16LKZpTZRJUjzBFokp9hF7u1fuGeE3D70ERXzdbMBOqQz7Q==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/middleware-sdk-s3@3.972.10': - resolution: {integrity: sha512-wLkB4bshbBtsAiC2WwlHzOWXu1fx3ftL63fQl0DxEda48Q6B8bcHydZppE3KjEIpPyiNOllByfSnb07cYpIgmw==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/middleware-ssec@3.972.3': - resolution: {integrity: sha512-dU6kDuULN3o3jEHcjm0c4zWJlY1zWVkjG9NPe9qxYLLpcbdj5kRYBS2DdWYD+1B9f910DezRuws7xDEqKkHQIg==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/middleware-user-agent@3.972.10': - resolution: {integrity: sha512-bBEL8CAqPQkI91ZM5a9xnFAzedpzH6NYCOtNyLarRAzTUTFN2DKqaC60ugBa7pnU1jSi4mA7WAXBsrod7nJltg==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/nested-clients@3.990.0': - resolution: {integrity: sha512-3NA0s66vsy8g7hPh36ZsUgO4SiMyrhwcYvuuNK1PezO52vX3hXDW4pQrC6OQLGKGJV0o6tbEyQtXb/mPs8zg8w==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/region-config-resolver@3.972.3': - resolution: {integrity: sha512-v4J8qYAWfOMcZ4MJUyatntOicTzEMaU7j3OpkRCGGFSL2NgXQ5VbxauIyORA+pxdKZ0qQG2tCQjQjZDlXEC3Ow==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/signature-v4-multi-region@3.990.0': - resolution: {integrity: sha512-O55s1eFmKi+2Ko5T1hbdxL6tFVONGscSVe9VRxS4m91Tlbo9iG2Q2HvKWq1DuKQAuUWSUfMmjrRt07JNzizr2A==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/token-providers@3.990.0': - resolution: {integrity: sha512-L3BtUb2v9XmYgQdfGBzbBtKMXaP5fV973y3Qdxeevs6oUTVXFmi/mV1+LnScA/1wVPJC9/hlK+1o5vbt7cG7EQ==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/types@3.973.1': - resolution: {integrity: sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/util-arn-parser@3.972.2': - resolution: {integrity: sha512-VkykWbqMjlSgBFDyrY3nOSqupMc6ivXuGmvci6Q3NnLq5kC+mKQe2QBZ4nrWRE/jqOxeFP2uYzLtwncYYcvQDg==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/util-endpoints@3.990.0': - resolution: {integrity: sha512-kVwtDc9LNI3tQZHEMNbkLIOpeDK8sRSTuT8eMnzGY+O+JImPisfSTjdh+jw9OTznu+MYZjQsv0258sazVKunYg==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/util-locate-window@3.965.4': - resolution: {integrity: sha512-H1onv5SkgPBK2P6JR2MjGgbOnttoNzSPIRoeZTNPZYyaplwGg50zS3amXvXqF0/qfXpWEC9rLWU564QTB9bSog==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/util-user-agent-browser@3.972.3': - resolution: {integrity: sha512-JurOwkRUcXD/5MTDBcqdyQ9eVedtAsZgw5rBwktsPTN7QtPiS2Ld1jkJepNgYoCufz1Wcut9iup7GJDoIHp8Fw==} - - '@aws-sdk/util-user-agent-node@3.972.8': - resolution: {integrity: sha512-XJZuT0LWsFCW1C8dEpPAXSa7h6Pb3krr2y//1X0Zidpcl0vmgY5nL/X0JuBZlntpBzaN3+U4hvKjuijyiiR8zw==} - engines: {node: '>=20.0.0'} - peerDependencies: - aws-crt: '>=1.0.0' - peerDependenciesMeta: - aws-crt: - optional: true - - '@aws-sdk/xml-builder@3.972.4': - resolution: {integrity: sha512-0zJ05ANfYqI6+rGqj8samZBFod0dPPousBjLEqg8WdxSgbMAkRgLyn81lP215Do0rFJ/17LIXwr7q0yK24mP6Q==} - engines: {node: '>=20.0.0'} - - '@aws/lambda-invoke-store@0.2.3': - resolution: {integrity: sha512-oLvsaPMTBejkkmHhjf09xTgk71mOqyr/409NKhRIL08If7AhVfUsJhVsx386uJaqNd42v9kWamQ9lFbkoC2dYw==} - engines: {node: '>=18.0.0'} - '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -1148,56 +982,67 @@ packages: resolution: {integrity: sha512-+xmiDGGaSfIIOXMzkhJ++Oa0Gwvl9oXUeIiwarsdRXSe27HUIvjbSIpPxvnNsRebsNdUo7uAiQVgBD1hVriwSQ==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.44.2': resolution: {integrity: sha512-bDHvhzOfORk3wt8yxIra8N4k/N0MnKInCW5OGZaeDYa/hMrdPaJzo7CSkjKZqX4JFUWjUGm88lI6QJLCM7lDrA==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.44.2': resolution: {integrity: sha512-NMsDEsDiYghTbeZWEGnNi4F0hSbGnsuOG+VnNvxkKg0IGDvFh7UVpM/14mnMwxRxUf9AdAVJgHPvKXf6FpMB7A==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.44.2': resolution: {integrity: sha512-lb5bxXnxXglVq+7imxykIp5xMq+idehfl+wOgiiix0191av84OqbjUED+PRC5OA8eFJYj5xAGcpAZ0pF2MnW+A==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-loongarch64-gnu@4.44.2': resolution: {integrity: sha512-Yl5Rdpf9pIc4GW1PmkUGHdMtbx0fBLE1//SxDmuf3X0dUC57+zMepow2LK0V21661cjXdTn8hO2tXDdAWAqE5g==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-powerpc64le-gnu@4.44.2': resolution: {integrity: sha512-03vUDH+w55s680YYryyr78jsO1RWU9ocRMaeV2vMniJJW/6HhoTBwyyiiTPVHNWLnhsnwcQ0oH3S9JSBEKuyqw==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-gnu@4.44.2': resolution: {integrity: sha512-iYtAqBg5eEMG4dEfVlkqo05xMOk6y/JXIToRca2bAWuqjrJYJlx/I7+Z+4hSrsWU8GdJDFPL4ktV3dy4yBSrzg==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.44.2': resolution: {integrity: sha512-e6vEbgaaqz2yEHqtkPXa28fFuBGmUJ0N2dOJK8YUfijejInt9gfCSA7YDdJ4nYlv67JfP3+PSWFX4IVw/xRIPg==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.44.2': resolution: {integrity: sha512-evFOtkmVdY3udE+0QKrV5wBx7bKI0iHz5yEVx5WqDJkxp9YQefy4Mpx3RajIVcM6o7jxTvVd/qpC1IXUhGc1Mw==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.44.2': resolution: {integrity: sha512-/bXb0bEsWMyEkIsUL2Yt5nFB5naLAwyOWMEviQfQY1x3l5WsLKgvZf66TM7UTfED6erckUVUJQ/jJ1FSpm3pRQ==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.44.2': resolution: {integrity: sha512-3D3OB1vSSBXmkGEZR27uiMRNiwN08/RVAcBKwhUYPaiZ8bcvdeEwWPvbnXvvXHY+A/7xluzcN+kaiOFNiOZwWg==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-win32-arm64-msvc@4.44.2': resolution: {integrity: sha512-VfU0fsMK+rwdK8mwODqYeM2hDrF2WiHaSmCBrS7gColkQft95/8tphyzv2EupVxn3iE0FI78wzffoULH1G+dkw==} @@ -1228,21 +1073,25 @@ packages: resolution: {integrity: sha512-eQfcsaxhFrv5FmtaA7+O1F9/2yFDNIoPZzV/ZvqvFz5bBXVc4FAm/1fVpBg8Po/kX1h0chBc7Xkpry3cabFW8w==} cpu: [arm64] os: [linux] + libc: [glibc] '@rspack/binding-linux-arm64-musl@1.7.6': resolution: {integrity: sha512-DfQXKiyPIl7i1yECHy4eAkSmlUzzsSAbOjgMuKn7pudsWf483jg0UUYutNgXSlBjc/QSUp7906Cg8oty9OfwPA==} cpu: [arm64] os: [linux] + libc: [musl] '@rspack/binding-linux-x64-gnu@1.7.6': resolution: {integrity: sha512-NdA+2X3lk2GGrMMnTGyYTzM3pn+zNjaqXqlgKmFBXvjfZqzSsKq3pdD1KHZCd5QHN+Fwvoszj0JFsquEVhE1og==} cpu: [x64] os: [linux] + libc: [glibc] '@rspack/binding-linux-x64-musl@1.7.6': resolution: {integrity: sha512-rEy6MHKob02t/77YNgr6dREyJ0e0tv1X6Xsg8Z5E7rPXead06zefUbfazj4RELYySWnM38ovZyJAkPx/gOn3VA==} cpu: [x64] os: [linux] + libc: [musl] '@rspack/binding-wasm32-wasi@1.7.6': resolution: {integrity: sha512-YupOrz0daSG+YBbCIgpDgzfMM38YpChv+afZpaxx5Ml7xPeAZIIdgWmLHnQ2rts73N2M1NspAiBwV00Xx0N4Vg==} @@ -1290,222 +1139,6 @@ packages: '@rspack/lite-tapable@1.1.0': resolution: {integrity: sha512-E2B0JhYFmVAwdDiG14+DW0Di4Ze4Jg10Pc4/lILUrd5DRCaklduz2OvJ5HYQ6G+hd+WTzqQb3QnDNfK4yvAFYw==} - '@smithy/abort-controller@4.2.8': - resolution: {integrity: sha512-peuVfkYHAmS5ybKxWcfraK7WBBP0J+rkfUcbHJJKQ4ir3UAUNQI+Y4Vt/PqSzGqgloJ5O1dk7+WzNL8wcCSXbw==} - engines: {node: '>=18.0.0'} - - '@smithy/chunked-blob-reader-native@4.2.1': - resolution: {integrity: sha512-lX9Ay+6LisTfpLid2zZtIhSEjHMZoAR5hHCR4H7tBz/Zkfr5ea8RcQ7Tk4mi0P76p4cN+Btz16Ffno7YHpKXnQ==} - engines: {node: '>=18.0.0'} - - '@smithy/chunked-blob-reader@5.2.0': - resolution: {integrity: sha512-WmU0TnhEAJLWvfSeMxBNe5xtbselEO8+4wG0NtZeL8oR21WgH1xiO37El+/Y+H/Ie4SCwBy3MxYWmOYaGgZueA==} - engines: {node: '>=18.0.0'} - - '@smithy/config-resolver@4.4.6': - resolution: {integrity: sha512-qJpzYC64kaj3S0fueiu3kXm8xPrR3PcXDPEgnaNMRn0EjNSZFoFjvbUp0YUDsRhN1CB90EnHJtbxWKevnH99UQ==} - engines: {node: '>=18.0.0'} - - '@smithy/core@3.23.0': - resolution: {integrity: sha512-Yq4UPVoQICM9zHnByLmG8632t2M0+yap4T7ANVw482J0W7HW0pOuxwVmeOwzJqX2Q89fkXz0Vybz55Wj2Xzrsg==} - engines: {node: '>=18.0.0'} - - '@smithy/credential-provider-imds@4.2.8': - resolution: {integrity: sha512-FNT0xHS1c/CPN8upqbMFP83+ul5YgdisfCfkZ86Jh2NSmnqw/AJ6x5pEogVCTVvSm7j9MopRU89bmDelxuDMYw==} - engines: {node: '>=18.0.0'} - - '@smithy/eventstream-codec@4.2.8': - resolution: {integrity: sha512-jS/O5Q14UsufqoGhov7dHLOPCzkYJl9QDzusI2Psh4wyYx/izhzvX9P4D69aTxcdfVhEPhjK+wYyn/PzLjKbbw==} - engines: {node: '>=18.0.0'} - - '@smithy/eventstream-serde-browser@4.2.8': - resolution: {integrity: sha512-MTfQT/CRQz5g24ayXdjg53V0mhucZth4PESoA5IhvaWVDTOQLfo8qI9vzqHcPsdd2v6sqfTYqF5L/l+pea5Uyw==} - engines: {node: '>=18.0.0'} - - '@smithy/eventstream-serde-config-resolver@4.3.8': - resolution: {integrity: sha512-ah12+luBiDGzBruhu3efNy1IlbwSEdNiw8fOZksoKoWW1ZHvO/04MQsdnws/9Aj+5b0YXSSN2JXKy/ClIsW8MQ==} - engines: {node: '>=18.0.0'} - - '@smithy/eventstream-serde-node@4.2.8': - resolution: {integrity: sha512-cYpCpp29z6EJHa5T9WL0KAlq3SOKUQkcgSoeRfRVwjGgSFl7Uh32eYGt7IDYCX20skiEdRffyDpvF2efEZPC0A==} - engines: {node: '>=18.0.0'} - - '@smithy/eventstream-serde-universal@4.2.8': - resolution: {integrity: sha512-iJ6YNJd0bntJYnX6s52NC4WFYcZeKrPUr1Kmmr5AwZcwCSzVpS7oavAmxMR7pMq7V+D1G4s9F5NJK0xwOsKAlQ==} - engines: {node: '>=18.0.0'} - - '@smithy/fetch-http-handler@5.3.9': - resolution: {integrity: sha512-I4UhmcTYXBrct03rwzQX1Y/iqQlzVQaPxWjCjula++5EmWq9YGBrx6bbGqluGc1f0XEfhSkiY4jhLgbsJUMKRA==} - engines: {node: '>=18.0.0'} - - '@smithy/hash-blob-browser@4.2.9': - resolution: {integrity: sha512-m80d/iicI7DlBDxyQP6Th7BW/ejDGiF0bgI754+tiwK0lgMkcaIBgvwwVc7OFbY4eUzpGtnig52MhPAEJ7iNYg==} - engines: {node: '>=18.0.0'} - - '@smithy/hash-node@4.2.8': - resolution: {integrity: sha512-7ZIlPbmaDGxVoxErDZnuFG18WekhbA/g2/i97wGj+wUBeS6pcUeAym8u4BXh/75RXWhgIJhyC11hBzig6MljwA==} - engines: {node: '>=18.0.0'} - - '@smithy/hash-stream-node@4.2.8': - resolution: {integrity: sha512-v0FLTXgHrTeheYZFGhR+ehX5qUm4IQsjAiL9qehad2cyjMWcN2QG6/4mSwbSgEQzI7jwfoXj7z4fxZUx/Mhj2w==} - engines: {node: '>=18.0.0'} - - '@smithy/invalid-dependency@4.2.8': - resolution: {integrity: sha512-N9iozRybwAQ2dn9Fot9kI6/w9vos2oTXLhtK7ovGqwZjlOcxu6XhPlpLpC+INsxktqHinn5gS2DXDjDF2kG5sQ==} - engines: {node: '>=18.0.0'} - - '@smithy/is-array-buffer@2.2.0': - resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} - engines: {node: '>=14.0.0'} - - '@smithy/is-array-buffer@4.2.0': - resolution: {integrity: sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==} - engines: {node: '>=18.0.0'} - - '@smithy/md5-js@4.2.8': - resolution: {integrity: sha512-oGMaLj4tVZzLi3itBa9TCswgMBr7k9b+qKYowQ6x1rTyTuO1IU2YHdHUa+891OsOH+wCsH7aTPRsTJO3RMQmjQ==} - engines: {node: '>=18.0.0'} - - '@smithy/middleware-content-length@4.2.8': - resolution: {integrity: sha512-RO0jeoaYAB1qBRhfVyq0pMgBoUK34YEJxVxyjOWYZiOKOq2yMZ4MnVXMZCUDenpozHue207+9P5ilTV1zeda0A==} - engines: {node: '>=18.0.0'} - - '@smithy/middleware-endpoint@4.4.14': - resolution: {integrity: sha512-FUFNE5KVeaY6U/GL0nzAAHkaCHzXLZcY1EhtQnsAqhD8Du13oPKtMB9/0WK4/LK6a/T5OZ24wPoSShff5iI6Ag==} - engines: {node: '>=18.0.0'} - - '@smithy/middleware-retry@4.4.31': - resolution: {integrity: sha512-RXBzLpMkIrxBPe4C8OmEOHvS8aH9RUuCOH++Acb5jZDEblxDjyg6un72X9IcbrGTJoiUwmI7hLypNfuDACypbg==} - engines: {node: '>=18.0.0'} - - '@smithy/middleware-serde@4.2.9': - resolution: {integrity: sha512-eMNiej0u/snzDvlqRGSN3Vl0ESn3838+nKyVfF2FKNXFbi4SERYT6PR392D39iczngbqqGG0Jl1DlCnp7tBbXQ==} - engines: {node: '>=18.0.0'} - - '@smithy/middleware-stack@4.2.8': - resolution: {integrity: sha512-w6LCfOviTYQjBctOKSwy6A8FIkQy7ICvglrZFl6Bw4FmcQ1Z420fUtIhxaUZZshRe0VCq4kvDiPiXrPZAe8oRA==} - engines: {node: '>=18.0.0'} - - '@smithy/node-config-provider@4.3.8': - resolution: {integrity: sha512-aFP1ai4lrbVlWjfpAfRSL8KFcnJQYfTl5QxLJXY32vghJrDuFyPZ6LtUL+JEGYiFRG1PfPLHLoxj107ulncLIg==} - engines: {node: '>=18.0.0'} - - '@smithy/node-http-handler@4.4.10': - resolution: {integrity: sha512-u4YeUwOWRZaHbWaebvrs3UhwQwj+2VNmcVCwXcYTvPIuVyM7Ex1ftAj+fdbG/P4AkBwLq/+SKn+ydOI4ZJE9PA==} - engines: {node: '>=18.0.0'} - - '@smithy/property-provider@4.2.8': - resolution: {integrity: sha512-EtCTbyIveCKeOXDSWSdze3k612yCPq1YbXsbqX3UHhkOSW8zKsM9NOJG5gTIya0vbY2DIaieG8pKo1rITHYL0w==} - engines: {node: '>=18.0.0'} - - '@smithy/protocol-http@5.3.8': - resolution: {integrity: sha512-QNINVDhxpZ5QnP3aviNHQFlRogQZDfYlCkQT+7tJnErPQbDhysondEjhikuANxgMsZrkGeiAxXy4jguEGsDrWQ==} - engines: {node: '>=18.0.0'} - - '@smithy/querystring-builder@4.2.8': - resolution: {integrity: sha512-Xr83r31+DrE8CP3MqPgMJl+pQlLLmOfiEUnoyAlGzzJIrEsbKsPy1hqH0qySaQm4oWrCBlUqRt+idEgunKB+iw==} - engines: {node: '>=18.0.0'} - - '@smithy/querystring-parser@4.2.8': - resolution: {integrity: sha512-vUurovluVy50CUlazOiXkPq40KGvGWSdmusa3130MwrR1UNnNgKAlj58wlOe61XSHRpUfIIh6cE0zZ8mzKaDPA==} - engines: {node: '>=18.0.0'} - - '@smithy/service-error-classification@4.2.8': - resolution: {integrity: sha512-mZ5xddodpJhEt3RkCjbmUQuXUOaPNTkbMGR0bcS8FE0bJDLMZlhmpgrvPNCYglVw5rsYTpSnv19womw9WWXKQQ==} - engines: {node: '>=18.0.0'} - - '@smithy/shared-ini-file-loader@4.4.3': - resolution: {integrity: sha512-DfQjxXQnzC5UbCUPeC3Ie8u+rIWZTvuDPAGU/BxzrOGhRvgUanaP68kDZA+jaT3ZI+djOf+4dERGlm9mWfFDrg==} - engines: {node: '>=18.0.0'} - - '@smithy/signature-v4@5.3.8': - resolution: {integrity: sha512-6A4vdGj7qKNRF16UIcO8HhHjKW27thsxYci+5r/uVRkdcBEkOEiY8OMPuydLX4QHSrJqGHPJzPRwwVTqbLZJhg==} - engines: {node: '>=18.0.0'} - - '@smithy/smithy-client@4.11.3': - resolution: {integrity: sha512-Q7kY5sDau8OoE6Y9zJoRGgje8P4/UY0WzH8R2ok0PDh+iJ+ZnEKowhjEqYafVcubkbYxQVaqwm3iufktzhprGg==} - engines: {node: '>=18.0.0'} - - '@smithy/types@4.12.0': - resolution: {integrity: sha512-9YcuJVTOBDjg9LWo23Qp0lTQ3D7fQsQtwle0jVfpbUHy9qBwCEgKuVH4FqFB3VYu0nwdHKiEMA+oXz7oV8X1kw==} - engines: {node: '>=18.0.0'} - - '@smithy/url-parser@4.2.8': - resolution: {integrity: sha512-NQho9U68TGMEU639YkXnVMV3GEFFULmmaWdlu1E9qzyIePOHsoSnagTGSDv1Zi8DCNN6btxOSdgmy5E/hsZwhA==} - engines: {node: '>=18.0.0'} - - '@smithy/util-base64@4.3.0': - resolution: {integrity: sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==} - engines: {node: '>=18.0.0'} - - '@smithy/util-body-length-browser@4.2.0': - resolution: {integrity: sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==} - engines: {node: '>=18.0.0'} - - '@smithy/util-body-length-node@4.2.1': - resolution: {integrity: sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==} - engines: {node: '>=18.0.0'} - - '@smithy/util-buffer-from@2.2.0': - resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} - engines: {node: '>=14.0.0'} - - '@smithy/util-buffer-from@4.2.0': - resolution: {integrity: sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==} - engines: {node: '>=18.0.0'} - - '@smithy/util-config-provider@4.2.0': - resolution: {integrity: sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==} - engines: {node: '>=18.0.0'} - - '@smithy/util-defaults-mode-browser@4.3.30': - resolution: {integrity: sha512-cMni0uVU27zxOiU8TuC8pQLC1pYeZ/xEMxvchSK/ILwleRd1ugobOcIRr5vXtcRqKd4aBLWlpeBoDPJJ91LQng==} - engines: {node: '>=18.0.0'} - - '@smithy/util-defaults-mode-node@4.2.33': - resolution: {integrity: sha512-LEb2aq5F4oZUSzWBG7S53d4UytZSkOEJPXcBq/xbG2/TmK9EW5naUZ8lKu1BEyWMzdHIzEVN16M3k8oxDq+DJA==} - engines: {node: '>=18.0.0'} - - '@smithy/util-endpoints@3.2.8': - resolution: {integrity: sha512-8JaVTn3pBDkhZgHQ8R0epwWt+BqPSLCjdjXXusK1onwJlRuN69fbvSK66aIKKO7SwVFM6x2J2ox5X8pOaWcUEw==} - engines: {node: '>=18.0.0'} - - '@smithy/util-hex-encoding@4.2.0': - resolution: {integrity: sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==} - engines: {node: '>=18.0.0'} - - '@smithy/util-middleware@4.2.8': - resolution: {integrity: sha512-PMqfeJxLcNPMDgvPbbLl/2Vpin+luxqTGPpW3NAQVLbRrFRzTa4rNAASYeIGjRV9Ytuhzny39SpyU04EQreF+A==} - engines: {node: '>=18.0.0'} - - '@smithy/util-retry@4.2.8': - resolution: {integrity: sha512-CfJqwvoRY0kTGe5AkQokpURNCT1u/MkRzMTASWMPPo2hNSnKtF1D45dQl3DE2LKLr4m+PW9mCeBMJr5mCAVThg==} - engines: {node: '>=18.0.0'} - - '@smithy/util-stream@4.5.12': - resolution: {integrity: sha512-D8tgkrmhAX/UNeCZbqbEO3uqyghUnEmmoO9YEvRuwxjlkKKUE7FOgCJnqpTlQPe9MApdWPky58mNQQHbnCzoNg==} - engines: {node: '>=18.0.0'} - - '@smithy/util-uri-escape@4.2.0': - resolution: {integrity: sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==} - engines: {node: '>=18.0.0'} - - '@smithy/util-utf8@2.3.0': - resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} - engines: {node: '>=14.0.0'} - - '@smithy/util-utf8@4.2.0': - resolution: {integrity: sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==} - engines: {node: '>=18.0.0'} - - '@smithy/util-waiter@4.2.8': - resolution: {integrity: sha512-n+lahlMWk+aejGuax7DPWtqav8HYnWxQwR+LCG2BgCUmaGcTe9qZCFsmw8TMg9iG75HOwhrJCX9TCJRLH+Yzqg==} - engines: {node: '>=18.0.0'} - - '@smithy/uuid@1.1.0': - resolution: {integrity: sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==} - engines: {node: '>=18.0.0'} - '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} @@ -2092,9 +1725,6 @@ packages: bonjour-service@1.3.0: resolution: {integrity: sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==} - bowser@2.14.1: - resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==} - brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} @@ -2687,10 +2317,6 @@ packages: fast-uri@3.0.3: resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} - fast-xml-parser@5.3.4: - resolution: {integrity: sha512-EFd6afGmXlCx8H8WTZHhAoDaWaGyuIBoZJ2mknrNxug+aZKjkp0a0dlars9Izl+jF+7Gu1/5f/2h68cQpe0IiA==} - hasBin: true - fast-xml-parser@5.3.5: resolution: {integrity: sha512-JeaA2Vm9ffQKp9VjvfzObuMCjUYAp5WDYhRYL5LrBPY/jUDlUtOvDfot0vKSkB9tuX885BDHjtw4fZadD95wnA==} hasBin: true @@ -4662,491 +4288,6 @@ snapshots: '@csstools/css-tokenizer': 3.0.4 lru-cache: 10.4.3 - '@aws-crypto/crc32@5.2.0': - dependencies: - '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.1 - tslib: 2.8.1 - - '@aws-crypto/crc32c@5.2.0': - dependencies: - '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.1 - tslib: 2.8.1 - - '@aws-crypto/sha1-browser@5.2.0': - dependencies: - '@aws-crypto/supports-web-crypto': 5.2.0 - '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-locate-window': 3.965.4 - '@smithy/util-utf8': 2.3.0 - tslib: 2.8.1 - - '@aws-crypto/sha256-browser@5.2.0': - dependencies: - '@aws-crypto/sha256-js': 5.2.0 - '@aws-crypto/supports-web-crypto': 5.2.0 - '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-locate-window': 3.965.4 - '@smithy/util-utf8': 2.3.0 - tslib: 2.8.1 - - '@aws-crypto/sha256-js@5.2.0': - dependencies: - '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.1 - tslib: 2.8.1 - - '@aws-crypto/supports-web-crypto@5.2.0': - dependencies: - tslib: 2.8.1 - - '@aws-crypto/util@5.2.0': - dependencies: - '@aws-sdk/types': 3.973.1 - '@smithy/util-utf8': 2.3.0 - tslib: 2.8.1 - - '@aws-sdk/client-s3@3.990.0': - dependencies: - '@aws-crypto/sha1-browser': 5.2.0 - '@aws-crypto/sha256-browser': 5.2.0 - '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.973.10 - '@aws-sdk/credential-provider-node': 3.972.9 - '@aws-sdk/middleware-bucket-endpoint': 3.972.3 - '@aws-sdk/middleware-expect-continue': 3.972.3 - '@aws-sdk/middleware-flexible-checksums': 3.972.8 - '@aws-sdk/middleware-host-header': 3.972.3 - '@aws-sdk/middleware-location-constraint': 3.972.3 - '@aws-sdk/middleware-logger': 3.972.3 - '@aws-sdk/middleware-recursion-detection': 3.972.3 - '@aws-sdk/middleware-sdk-s3': 3.972.10 - '@aws-sdk/middleware-ssec': 3.972.3 - '@aws-sdk/middleware-user-agent': 3.972.10 - '@aws-sdk/region-config-resolver': 3.972.3 - '@aws-sdk/signature-v4-multi-region': 3.990.0 - '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-endpoints': 3.990.0 - '@aws-sdk/util-user-agent-browser': 3.972.3 - '@aws-sdk/util-user-agent-node': 3.972.8 - '@smithy/config-resolver': 4.4.6 - '@smithy/core': 3.23.0 - '@smithy/eventstream-serde-browser': 4.2.8 - '@smithy/eventstream-serde-config-resolver': 4.3.8 - '@smithy/eventstream-serde-node': 4.2.8 - '@smithy/fetch-http-handler': 5.3.9 - '@smithy/hash-blob-browser': 4.2.9 - '@smithy/hash-node': 4.2.8 - '@smithy/hash-stream-node': 4.2.8 - '@smithy/invalid-dependency': 4.2.8 - '@smithy/md5-js': 4.2.8 - '@smithy/middleware-content-length': 4.2.8 - '@smithy/middleware-endpoint': 4.4.14 - '@smithy/middleware-retry': 4.4.31 - '@smithy/middleware-serde': 4.2.9 - '@smithy/middleware-stack': 4.2.8 - '@smithy/node-config-provider': 4.3.8 - '@smithy/node-http-handler': 4.4.10 - '@smithy/protocol-http': 5.3.8 - '@smithy/smithy-client': 4.11.3 - '@smithy/types': 4.12.0 - '@smithy/url-parser': 4.2.8 - '@smithy/util-base64': 4.3.0 - '@smithy/util-body-length-browser': 4.2.0 - '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.30 - '@smithy/util-defaults-mode-node': 4.2.33 - '@smithy/util-endpoints': 3.2.8 - '@smithy/util-middleware': 4.2.8 - '@smithy/util-retry': 4.2.8 - '@smithy/util-stream': 4.5.12 - '@smithy/util-utf8': 4.2.0 - '@smithy/util-waiter': 4.2.8 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/client-sso@3.990.0': - dependencies: - '@aws-crypto/sha256-browser': 5.2.0 - '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.973.10 - '@aws-sdk/middleware-host-header': 3.972.3 - '@aws-sdk/middleware-logger': 3.972.3 - '@aws-sdk/middleware-recursion-detection': 3.972.3 - '@aws-sdk/middleware-user-agent': 3.972.10 - '@aws-sdk/region-config-resolver': 3.972.3 - '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-endpoints': 3.990.0 - '@aws-sdk/util-user-agent-browser': 3.972.3 - '@aws-sdk/util-user-agent-node': 3.972.8 - '@smithy/config-resolver': 4.4.6 - '@smithy/core': 3.23.0 - '@smithy/fetch-http-handler': 5.3.9 - '@smithy/hash-node': 4.2.8 - '@smithy/invalid-dependency': 4.2.8 - '@smithy/middleware-content-length': 4.2.8 - '@smithy/middleware-endpoint': 4.4.14 - '@smithy/middleware-retry': 4.4.31 - '@smithy/middleware-serde': 4.2.9 - '@smithy/middleware-stack': 4.2.8 - '@smithy/node-config-provider': 4.3.8 - '@smithy/node-http-handler': 4.4.10 - '@smithy/protocol-http': 5.3.8 - '@smithy/smithy-client': 4.11.3 - '@smithy/types': 4.12.0 - '@smithy/url-parser': 4.2.8 - '@smithy/util-base64': 4.3.0 - '@smithy/util-body-length-browser': 4.2.0 - '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.30 - '@smithy/util-defaults-mode-node': 4.2.33 - '@smithy/util-endpoints': 3.2.8 - '@smithy/util-middleware': 4.2.8 - '@smithy/util-retry': 4.2.8 - '@smithy/util-utf8': 4.2.0 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/core@3.973.10': - dependencies: - '@aws-sdk/types': 3.973.1 - '@aws-sdk/xml-builder': 3.972.4 - '@smithy/core': 3.23.0 - '@smithy/node-config-provider': 4.3.8 - '@smithy/property-provider': 4.2.8 - '@smithy/protocol-http': 5.3.8 - '@smithy/signature-v4': 5.3.8 - '@smithy/smithy-client': 4.11.3 - '@smithy/types': 4.12.0 - '@smithy/util-base64': 4.3.0 - '@smithy/util-middleware': 4.2.8 - '@smithy/util-utf8': 4.2.0 - tslib: 2.8.1 - - '@aws-sdk/crc64-nvme@3.972.0': - dependencies: - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-env@3.972.8': - dependencies: - '@aws-sdk/core': 3.973.10 - '@aws-sdk/types': 3.973.1 - '@smithy/property-provider': 4.2.8 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-http@3.972.10': - dependencies: - '@aws-sdk/core': 3.973.10 - '@aws-sdk/types': 3.973.1 - '@smithy/fetch-http-handler': 5.3.9 - '@smithy/node-http-handler': 4.4.10 - '@smithy/property-provider': 4.2.8 - '@smithy/protocol-http': 5.3.8 - '@smithy/smithy-client': 4.11.3 - '@smithy/types': 4.12.0 - '@smithy/util-stream': 4.5.12 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-ini@3.972.8': - dependencies: - '@aws-sdk/core': 3.973.10 - '@aws-sdk/credential-provider-env': 3.972.8 - '@aws-sdk/credential-provider-http': 3.972.10 - '@aws-sdk/credential-provider-login': 3.972.8 - '@aws-sdk/credential-provider-process': 3.972.8 - '@aws-sdk/credential-provider-sso': 3.972.8 - '@aws-sdk/credential-provider-web-identity': 3.972.8 - '@aws-sdk/nested-clients': 3.990.0 - '@aws-sdk/types': 3.973.1 - '@smithy/credential-provider-imds': 4.2.8 - '@smithy/property-provider': 4.2.8 - '@smithy/shared-ini-file-loader': 4.4.3 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/credential-provider-login@3.972.8': - dependencies: - '@aws-sdk/core': 3.973.10 - '@aws-sdk/nested-clients': 3.990.0 - '@aws-sdk/types': 3.973.1 - '@smithy/property-provider': 4.2.8 - '@smithy/protocol-http': 5.3.8 - '@smithy/shared-ini-file-loader': 4.4.3 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/credential-provider-node@3.972.9': - dependencies: - '@aws-sdk/credential-provider-env': 3.972.8 - '@aws-sdk/credential-provider-http': 3.972.10 - '@aws-sdk/credential-provider-ini': 3.972.8 - '@aws-sdk/credential-provider-process': 3.972.8 - '@aws-sdk/credential-provider-sso': 3.972.8 - '@aws-sdk/credential-provider-web-identity': 3.972.8 - '@aws-sdk/types': 3.973.1 - '@smithy/credential-provider-imds': 4.2.8 - '@smithy/property-provider': 4.2.8 - '@smithy/shared-ini-file-loader': 4.4.3 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/credential-provider-process@3.972.8': - dependencies: - '@aws-sdk/core': 3.973.10 - '@aws-sdk/types': 3.973.1 - '@smithy/property-provider': 4.2.8 - '@smithy/shared-ini-file-loader': 4.4.3 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@aws-sdk/credential-provider-sso@3.972.8': - dependencies: - '@aws-sdk/client-sso': 3.990.0 - '@aws-sdk/core': 3.973.10 - '@aws-sdk/token-providers': 3.990.0 - '@aws-sdk/types': 3.973.1 - '@smithy/property-provider': 4.2.8 - '@smithy/shared-ini-file-loader': 4.4.3 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/credential-provider-web-identity@3.972.8': - dependencies: - '@aws-sdk/core': 3.973.10 - '@aws-sdk/nested-clients': 3.990.0 - '@aws-sdk/types': 3.973.1 - '@smithy/property-provider': 4.2.8 - '@smithy/shared-ini-file-loader': 4.4.3 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/middleware-bucket-endpoint@3.972.3': - dependencies: - '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-arn-parser': 3.972.2 - '@smithy/node-config-provider': 4.3.8 - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 - '@smithy/util-config-provider': 4.2.0 - tslib: 2.8.1 - - '@aws-sdk/middleware-expect-continue@3.972.3': - dependencies: - '@aws-sdk/types': 3.973.1 - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@aws-sdk/middleware-flexible-checksums@3.972.8': - dependencies: - '@aws-crypto/crc32': 5.2.0 - '@aws-crypto/crc32c': 5.2.0 - '@aws-crypto/util': 5.2.0 - '@aws-sdk/core': 3.973.10 - '@aws-sdk/crc64-nvme': 3.972.0 - '@aws-sdk/types': 3.973.1 - '@smithy/is-array-buffer': 4.2.0 - '@smithy/node-config-provider': 4.3.8 - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 - '@smithy/util-middleware': 4.2.8 - '@smithy/util-stream': 4.5.12 - '@smithy/util-utf8': 4.2.0 - tslib: 2.8.1 - - '@aws-sdk/middleware-host-header@3.972.3': - dependencies: - '@aws-sdk/types': 3.973.1 - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@aws-sdk/middleware-location-constraint@3.972.3': - dependencies: - '@aws-sdk/types': 3.973.1 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@aws-sdk/middleware-logger@3.972.3': - dependencies: - '@aws-sdk/types': 3.973.1 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@aws-sdk/middleware-recursion-detection@3.972.3': - dependencies: - '@aws-sdk/types': 3.973.1 - '@aws/lambda-invoke-store': 0.2.3 - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@aws-sdk/middleware-sdk-s3@3.972.10': - dependencies: - '@aws-sdk/core': 3.973.10 - '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-arn-parser': 3.972.2 - '@smithy/core': 3.23.0 - '@smithy/node-config-provider': 4.3.8 - '@smithy/protocol-http': 5.3.8 - '@smithy/signature-v4': 5.3.8 - '@smithy/smithy-client': 4.11.3 - '@smithy/types': 4.12.0 - '@smithy/util-config-provider': 4.2.0 - '@smithy/util-middleware': 4.2.8 - '@smithy/util-stream': 4.5.12 - '@smithy/util-utf8': 4.2.0 - tslib: 2.8.1 - - '@aws-sdk/middleware-ssec@3.972.3': - dependencies: - '@aws-sdk/types': 3.973.1 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@aws-sdk/middleware-user-agent@3.972.10': - dependencies: - '@aws-sdk/core': 3.973.10 - '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-endpoints': 3.990.0 - '@smithy/core': 3.23.0 - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@aws-sdk/nested-clients@3.990.0': - dependencies: - '@aws-crypto/sha256-browser': 5.2.0 - '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.973.10 - '@aws-sdk/middleware-host-header': 3.972.3 - '@aws-sdk/middleware-logger': 3.972.3 - '@aws-sdk/middleware-recursion-detection': 3.972.3 - '@aws-sdk/middleware-user-agent': 3.972.10 - '@aws-sdk/region-config-resolver': 3.972.3 - '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-endpoints': 3.990.0 - '@aws-sdk/util-user-agent-browser': 3.972.3 - '@aws-sdk/util-user-agent-node': 3.972.8 - '@smithy/config-resolver': 4.4.6 - '@smithy/core': 3.23.0 - '@smithy/fetch-http-handler': 5.3.9 - '@smithy/hash-node': 4.2.8 - '@smithy/invalid-dependency': 4.2.8 - '@smithy/middleware-content-length': 4.2.8 - '@smithy/middleware-endpoint': 4.4.14 - '@smithy/middleware-retry': 4.4.31 - '@smithy/middleware-serde': 4.2.9 - '@smithy/middleware-stack': 4.2.8 - '@smithy/node-config-provider': 4.3.8 - '@smithy/node-http-handler': 4.4.10 - '@smithy/protocol-http': 5.3.8 - '@smithy/smithy-client': 4.11.3 - '@smithy/types': 4.12.0 - '@smithy/url-parser': 4.2.8 - '@smithy/util-base64': 4.3.0 - '@smithy/util-body-length-browser': 4.2.0 - '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.30 - '@smithy/util-defaults-mode-node': 4.2.33 - '@smithy/util-endpoints': 3.2.8 - '@smithy/util-middleware': 4.2.8 - '@smithy/util-retry': 4.2.8 - '@smithy/util-utf8': 4.2.0 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/region-config-resolver@3.972.3': - dependencies: - '@aws-sdk/types': 3.973.1 - '@smithy/config-resolver': 4.4.6 - '@smithy/node-config-provider': 4.3.8 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@aws-sdk/signature-v4-multi-region@3.990.0': - dependencies: - '@aws-sdk/middleware-sdk-s3': 3.972.10 - '@aws-sdk/types': 3.973.1 - '@smithy/protocol-http': 5.3.8 - '@smithy/signature-v4': 5.3.8 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@aws-sdk/token-providers@3.990.0': - dependencies: - '@aws-sdk/core': 3.973.10 - '@aws-sdk/nested-clients': 3.990.0 - '@aws-sdk/types': 3.973.1 - '@smithy/property-provider': 4.2.8 - '@smithy/shared-ini-file-loader': 4.4.3 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/types@3.973.1': - dependencies: - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@aws-sdk/util-arn-parser@3.972.2': - dependencies: - tslib: 2.8.1 - - '@aws-sdk/util-endpoints@3.990.0': - dependencies: - '@aws-sdk/types': 3.973.1 - '@smithy/types': 4.12.0 - '@smithy/url-parser': 4.2.8 - '@smithy/util-endpoints': 3.2.8 - tslib: 2.8.1 - - '@aws-sdk/util-locate-window@3.965.4': - dependencies: - tslib: 2.8.1 - - '@aws-sdk/util-user-agent-browser@3.972.3': - dependencies: - '@aws-sdk/types': 3.973.1 - '@smithy/types': 4.12.0 - bowser: 2.14.1 - tslib: 2.8.1 - - '@aws-sdk/util-user-agent-node@3.972.8': - dependencies: - '@aws-sdk/middleware-user-agent': 3.972.10 - '@aws-sdk/types': 3.973.1 - '@smithy/node-config-provider': 4.3.8 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@aws-sdk/xml-builder@3.972.4': - dependencies: - '@smithy/types': 4.12.0 - fast-xml-parser: 5.3.4 - tslib: 2.8.1 - - '@aws/lambda-invoke-store@0.2.3': {} - '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.28.5 @@ -5906,344 +5047,6 @@ snapshots: '@rspack/lite-tapable@1.1.0': {} - '@smithy/abort-controller@4.2.8': - dependencies: - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/chunked-blob-reader-native@4.2.1': - dependencies: - '@smithy/util-base64': 4.3.0 - tslib: 2.8.1 - - '@smithy/chunked-blob-reader@5.2.0': - dependencies: - tslib: 2.8.1 - - '@smithy/config-resolver@4.4.6': - dependencies: - '@smithy/node-config-provider': 4.3.8 - '@smithy/types': 4.12.0 - '@smithy/util-config-provider': 4.2.0 - '@smithy/util-endpoints': 3.2.8 - '@smithy/util-middleware': 4.2.8 - tslib: 2.8.1 - - '@smithy/core@3.23.0': - dependencies: - '@smithy/middleware-serde': 4.2.9 - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 - '@smithy/util-base64': 4.3.0 - '@smithy/util-body-length-browser': 4.2.0 - '@smithy/util-middleware': 4.2.8 - '@smithy/util-stream': 4.5.12 - '@smithy/util-utf8': 4.2.0 - '@smithy/uuid': 1.1.0 - tslib: 2.8.1 - - '@smithy/credential-provider-imds@4.2.8': - dependencies: - '@smithy/node-config-provider': 4.3.8 - '@smithy/property-provider': 4.2.8 - '@smithy/types': 4.12.0 - '@smithy/url-parser': 4.2.8 - tslib: 2.8.1 - - '@smithy/eventstream-codec@4.2.8': - dependencies: - '@aws-crypto/crc32': 5.2.0 - '@smithy/types': 4.12.0 - '@smithy/util-hex-encoding': 4.2.0 - tslib: 2.8.1 - - '@smithy/eventstream-serde-browser@4.2.8': - dependencies: - '@smithy/eventstream-serde-universal': 4.2.8 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/eventstream-serde-config-resolver@4.3.8': - dependencies: - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/eventstream-serde-node@4.2.8': - dependencies: - '@smithy/eventstream-serde-universal': 4.2.8 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/eventstream-serde-universal@4.2.8': - dependencies: - '@smithy/eventstream-codec': 4.2.8 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/fetch-http-handler@5.3.9': - dependencies: - '@smithy/protocol-http': 5.3.8 - '@smithy/querystring-builder': 4.2.8 - '@smithy/types': 4.12.0 - '@smithy/util-base64': 4.3.0 - tslib: 2.8.1 - - '@smithy/hash-blob-browser@4.2.9': - dependencies: - '@smithy/chunked-blob-reader': 5.2.0 - '@smithy/chunked-blob-reader-native': 4.2.1 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/hash-node@4.2.8': - dependencies: - '@smithy/types': 4.12.0 - '@smithy/util-buffer-from': 4.2.0 - '@smithy/util-utf8': 4.2.0 - tslib: 2.8.1 - - '@smithy/hash-stream-node@4.2.8': - dependencies: - '@smithy/types': 4.12.0 - '@smithy/util-utf8': 4.2.0 - tslib: 2.8.1 - - '@smithy/invalid-dependency@4.2.8': - dependencies: - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/is-array-buffer@2.2.0': - dependencies: - tslib: 2.8.1 - - '@smithy/is-array-buffer@4.2.0': - dependencies: - tslib: 2.8.1 - - '@smithy/md5-js@4.2.8': - dependencies: - '@smithy/types': 4.12.0 - '@smithy/util-utf8': 4.2.0 - tslib: 2.8.1 - - '@smithy/middleware-content-length@4.2.8': - dependencies: - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/middleware-endpoint@4.4.14': - dependencies: - '@smithy/core': 3.23.0 - '@smithy/middleware-serde': 4.2.9 - '@smithy/node-config-provider': 4.3.8 - '@smithy/shared-ini-file-loader': 4.4.3 - '@smithy/types': 4.12.0 - '@smithy/url-parser': 4.2.8 - '@smithy/util-middleware': 4.2.8 - tslib: 2.8.1 - - '@smithy/middleware-retry@4.4.31': - dependencies: - '@smithy/node-config-provider': 4.3.8 - '@smithy/protocol-http': 5.3.8 - '@smithy/service-error-classification': 4.2.8 - '@smithy/smithy-client': 4.11.3 - '@smithy/types': 4.12.0 - '@smithy/util-middleware': 4.2.8 - '@smithy/util-retry': 4.2.8 - '@smithy/uuid': 1.1.0 - tslib: 2.8.1 - - '@smithy/middleware-serde@4.2.9': - dependencies: - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/middleware-stack@4.2.8': - dependencies: - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/node-config-provider@4.3.8': - dependencies: - '@smithy/property-provider': 4.2.8 - '@smithy/shared-ini-file-loader': 4.4.3 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/node-http-handler@4.4.10': - dependencies: - '@smithy/abort-controller': 4.2.8 - '@smithy/protocol-http': 5.3.8 - '@smithy/querystring-builder': 4.2.8 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/property-provider@4.2.8': - dependencies: - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/protocol-http@5.3.8': - dependencies: - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/querystring-builder@4.2.8': - dependencies: - '@smithy/types': 4.12.0 - '@smithy/util-uri-escape': 4.2.0 - tslib: 2.8.1 - - '@smithy/querystring-parser@4.2.8': - dependencies: - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/service-error-classification@4.2.8': - dependencies: - '@smithy/types': 4.12.0 - - '@smithy/shared-ini-file-loader@4.4.3': - dependencies: - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/signature-v4@5.3.8': - dependencies: - '@smithy/is-array-buffer': 4.2.0 - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 - '@smithy/util-hex-encoding': 4.2.0 - '@smithy/util-middleware': 4.2.8 - '@smithy/util-uri-escape': 4.2.0 - '@smithy/util-utf8': 4.2.0 - tslib: 2.8.1 - - '@smithy/smithy-client@4.11.3': - dependencies: - '@smithy/core': 3.23.0 - '@smithy/middleware-endpoint': 4.4.14 - '@smithy/middleware-stack': 4.2.8 - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 - '@smithy/util-stream': 4.5.12 - tslib: 2.8.1 - - '@smithy/types@4.12.0': - dependencies: - tslib: 2.8.1 - - '@smithy/url-parser@4.2.8': - dependencies: - '@smithy/querystring-parser': 4.2.8 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/util-base64@4.3.0': - dependencies: - '@smithy/util-buffer-from': 4.2.0 - '@smithy/util-utf8': 4.2.0 - tslib: 2.8.1 - - '@smithy/util-body-length-browser@4.2.0': - dependencies: - tslib: 2.8.1 - - '@smithy/util-body-length-node@4.2.1': - dependencies: - tslib: 2.8.1 - - '@smithy/util-buffer-from@2.2.0': - dependencies: - '@smithy/is-array-buffer': 2.2.0 - tslib: 2.8.1 - - '@smithy/util-buffer-from@4.2.0': - dependencies: - '@smithy/is-array-buffer': 4.2.0 - tslib: 2.8.1 - - '@smithy/util-config-provider@4.2.0': - dependencies: - tslib: 2.8.1 - - '@smithy/util-defaults-mode-browser@4.3.30': - dependencies: - '@smithy/property-provider': 4.2.8 - '@smithy/smithy-client': 4.11.3 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/util-defaults-mode-node@4.2.33': - dependencies: - '@smithy/config-resolver': 4.4.6 - '@smithy/credential-provider-imds': 4.2.8 - '@smithy/node-config-provider': 4.3.8 - '@smithy/property-provider': 4.2.8 - '@smithy/smithy-client': 4.11.3 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/util-endpoints@3.2.8': - dependencies: - '@smithy/node-config-provider': 4.3.8 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/util-hex-encoding@4.2.0': - dependencies: - tslib: 2.8.1 - - '@smithy/util-middleware@4.2.8': - dependencies: - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/util-retry@4.2.8': - dependencies: - '@smithy/service-error-classification': 4.2.8 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/util-stream@4.5.12': - dependencies: - '@smithy/fetch-http-handler': 5.3.9 - '@smithy/node-http-handler': 4.4.10 - '@smithy/types': 4.12.0 - '@smithy/util-base64': 4.3.0 - '@smithy/util-buffer-from': 4.2.0 - '@smithy/util-hex-encoding': 4.2.0 - '@smithy/util-utf8': 4.2.0 - tslib: 2.8.1 - - '@smithy/util-uri-escape@4.2.0': - dependencies: - tslib: 2.8.1 - - '@smithy/util-utf8@2.3.0': - dependencies: - '@smithy/util-buffer-from': 2.2.0 - tslib: 2.8.1 - - '@smithy/util-utf8@4.2.0': - dependencies: - '@smithy/util-buffer-from': 4.2.0 - tslib: 2.8.1 - - '@smithy/util-waiter@4.2.8': - dependencies: - '@smithy/abort-controller': 4.2.8 - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@smithy/uuid@1.1.0': - dependencies: - tslib: 2.8.1 - '@standard-schema/spec@1.1.0': {} '@swc/helpers@0.5.17': @@ -7058,8 +5861,6 @@ snapshots: fast-deep-equal: 3.1.3 multicast-dns: 7.2.5 - bowser@2.14.1: {} - brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 @@ -7790,10 +6591,6 @@ snapshots: fast-uri@3.0.3: {} - fast-xml-parser@5.3.4: - dependencies: - strnum: 2.1.2 - fast-xml-parser@5.3.5: dependencies: strnum: 2.1.2 From 53945f45aa13ec8f34bddda793da8b1190d47d2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E4=B8=80=E4=B9=8B?= Date: Sun, 15 Feb 2026 21:47:05 +0800 Subject: [PATCH 13/15] =?UTF-8?q?=E4=BB=8Econfig=E4=B8=AD=E8=8E=B7?= =?UTF-8?q?=E5=8F=96region?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/filesystem/s3/s3.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/filesystem/s3/s3.ts b/packages/filesystem/s3/s3.ts index b03cc23c6..ba048e248 100644 --- a/packages/filesystem/s3/s3.ts +++ b/packages/filesystem/s3/s3.ts @@ -51,8 +51,6 @@ export default class S3FileSystem implements FileSystem { bucket: string; - region: string = ""; - basePath: string = "/"; constructor(bucket: string, client: S3Client, basePath?: string); @@ -78,11 +76,10 @@ export default class S3FileSystem implements FileSystem { this.basePath = accessKeyIdOrBasePath || "/"; return; } - this.region = regionOrClient || "us-east-1"; this.basePath = basePath || "/"; const config: S3ClientConfig = { - region: this.region, + region: regionOrClient || "us-east-1", credentials: { accessKeyId: accessKeyIdOrBasePath!, secretAccessKey: secretAccessKey!, @@ -267,6 +264,6 @@ export default class S3FileSystem implements FileSystem { const url = this.client.getEndpointUrl(); return `${url}/${this.bucket}/${prefix}`; } - return `https://s3.console.aws.amazon.com/s3/buckets/${this.bucket}?prefix=${encodeURIComponent(prefix)}®ion=${this.region}`; + return `https://s3.console.aws.amazon.com/s3/buckets/${this.bucket}?prefix=${encodeURIComponent(prefix)}®ion=${this.client.getRegion()}`; } } From 6cf87676efe202098c6c2d4f3d2170d6ae75d637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E4=B8=80=E4=B9=8B?= Date: Sun, 15 Feb 2026 23:07:17 +0800 Subject: [PATCH 14/15] =?UTF-8?q?=E4=BD=BF=E7=94=A8=20fast-xml-parser=20?= =?UTF-8?q?=E5=A4=84=E7=90=86xml=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + packages/filesystem/s3/client.ts | 11 +++++++---- packages/filesystem/s3/s3.ts | 31 ++++++++++++++++++------------- pnpm-lock.yaml | 11 +++++++---- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index fa7228c66..67aa9f829 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "dexie": "^4.0.10", "eslint-linter-browserify": "9.26.0", "eventemitter3": "^5.0.1", + "fast-xml-parser": "^5.3.6", "i18next": "^23.16.4", "monaco-editor": "^0.52.2", "react": "^18.3.1", diff --git a/packages/filesystem/s3/client.ts b/packages/filesystem/s3/client.ts index 3180cb4f1..7b28f87aa 100644 --- a/packages/filesystem/s3/client.ts +++ b/packages/filesystem/s3/client.ts @@ -4,6 +4,8 @@ * 不依赖 @aws-sdk/client-s3 */ +import { XMLParser } from "fast-xml-parser"; + export interface S3ClientConfig { region: string; credentials: { @@ -107,10 +109,11 @@ async function parseS3Error(response: Response): Promise { try { const text = await response.text(); if (text) { - const codeMatch = text.match(/(.*?)<\/Code>/); - const messageMatch = text.match(/(.*?)<\/Message>/); - if (codeMatch) { - return new S3Error(codeMatch[1], messageMatch?.[1] || response.statusText, response.status); + const parser = new XMLParser(); + const parsed = parser.parse(text); + const error = parsed.Error; + if (error?.Code) { + return new S3Error(String(error.Code), String(error.Message || response.statusText), response.status); } } } catch { diff --git a/packages/filesystem/s3/s3.ts b/packages/filesystem/s3/s3.ts index ba048e248..41ce89e6a 100644 --- a/packages/filesystem/s3/s3.ts +++ b/packages/filesystem/s3/s3.ts @@ -1,3 +1,4 @@ +import { XMLParser } from "fast-xml-parser"; import { S3Client, S3Error } from "./client"; import type { S3ClientConfig } from "./client"; import type FileSystem from "../filesystem"; @@ -19,22 +20,26 @@ interface ListObjectsV2Result { nextContinuationToken?: string; } +const xmlParser = new XMLParser({ + // 不将单个元素包装成数组,后续手动处理 + isArray: (name) => name === "Contents", +}); + /** 从 ListObjectsV2 XML 响应中解析对象列表 */ function parseListObjectsV2(xml: string): ListObjectsV2Result { - const contents: ListObjectsV2Result["contents"] = []; - const contentsRegex = /([\s\S]*?)<\/Contents>/g; - let match; - while ((match = contentsRegex.exec(xml)) !== null) { - const block = match[1]; - const key = block.match(/([\s\S]*?)<\/Key>/)?.[1] || ""; - const lastModified = block.match(/([\s\S]*?)<\/LastModified>/)?.[1] || ""; - const etag = block.match(/([\s\S]*?)<\/ETag>/)?.[1] || ""; - const size = parseInt(block.match(/([\s\S]*?)<\/Size>/)?.[1] || "0", 10); - contents.push({ key, lastModified, etag, size }); - } + const parsed = xmlParser.parse(xml); + const result = parsed.ListBucketResult || parsed; + + const rawContents: any[] = result.Contents || []; + const contents: ListObjectsV2Result["contents"] = rawContents.map((obj: any) => ({ + key: String(obj.Key || ""), + lastModified: String(obj.LastModified || ""), + etag: String(obj.ETag || ""), + size: Number(obj.Size) || 0, + })); - const isTruncated = /true<\/IsTruncated>/.test(xml); - const nextToken = xml.match(/([\s\S]*?)<\/NextContinuationToken>/)?.[1]; + const isTruncated = result.IsTruncated === true || result.IsTruncated === "true"; + const nextToken = result.NextContinuationToken ? String(result.NextContinuationToken) : undefined; return { contents, isTruncated, nextContinuationToken: nextToken }; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c530ea985..d8413c881 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -44,6 +44,9 @@ importers: eventemitter3: specifier: ^5.0.1 version: 5.0.1 + fast-xml-parser: + specifier: ^5.3.6 + version: 5.3.6 i18next: specifier: ^23.16.4 version: 23.16.4 @@ -2317,8 +2320,8 @@ packages: fast-uri@3.0.3: resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} - fast-xml-parser@5.3.5: - resolution: {integrity: sha512-JeaA2Vm9ffQKp9VjvfzObuMCjUYAp5WDYhRYL5LrBPY/jUDlUtOvDfot0vKSkB9tuX885BDHjtw4fZadD95wnA==} + fast-xml-parser@5.3.6: + resolution: {integrity: sha512-QNI3sAvSvaOiaMl8FYU4trnEzCwiRr8XMWgAHzlrWpTSj+QaCSvOf1h82OEP1s4hiAXhnbXSyFWCf4ldZzZRVA==} hasBin: true fastq@1.17.1: @@ -6591,7 +6594,7 @@ snapshots: fast-uri@3.0.3: {} - fast-xml-parser@5.3.5: + fast-xml-parser@5.3.6: dependencies: strnum: 2.1.2 @@ -8480,7 +8483,7 @@ snapshots: base-64: 1.0.0 byte-length: 1.0.2 entities: 6.0.1 - fast-xml-parser: 5.3.5 + fast-xml-parser: 5.3.6 hot-patcher: 2.0.1 layerr: 3.0.0 md5: 2.3.0 From 6709e80e3f1a44c033c0c74888b3a9aaa722b9fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E4=B8=80=E4=B9=8B?= Date: Sun, 15 Feb 2026 23:28:10 +0800 Subject: [PATCH 15/15] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8D=95=E5=85=83?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/filesystem/s3/client.test.ts | 304 +++++++++++++++++++ packages/filesystem/s3/s3.test.ts | 413 ++++++++++++++++++++++++++ 2 files changed, 717 insertions(+) create mode 100644 packages/filesystem/s3/client.test.ts create mode 100644 packages/filesystem/s3/s3.test.ts diff --git a/packages/filesystem/s3/client.test.ts b/packages/filesystem/s3/client.test.ts new file mode 100644 index 000000000..29bc234a8 --- /dev/null +++ b/packages/filesystem/s3/client.test.ts @@ -0,0 +1,304 @@ +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; +import { S3Client, S3Error } from "./client"; +import type { S3ClientConfig } from "./client"; + +// ---- S3Error ---- +describe("S3Error", () => { + it("应当正确设置 code、message、statusCode 属性", () => { + const err = new S3Error("NoSuchKey", "The specified key does not exist", 404); + + expect(err).toBeInstanceOf(Error); + expect(err).toBeInstanceOf(S3Error); + expect(err.code).toBe("NoSuchKey"); + expect(err.name).toBe("NoSuchKey"); // 兼容 SDK error.name 检查 + expect(err.message).toBe("The specified key does not exist"); + expect(err.statusCode).toBe(404); + }); + + it("应当可被 try/catch 捕获并通过 instanceof 判断", () => { + try { + throw new S3Error("AccessDenied", "Access Denied", 403); + } catch (e) { + expect(e).toBeInstanceOf(S3Error); + if (e instanceof S3Error) { + expect(e.code).toBe("AccessDenied"); + expect(e.statusCode).toBe(403); + } + } + }); +}); + +// ---- S3Client 构造函数与 getter 方法 ---- +describe("S3Client", () => { + const defaultConfig: S3ClientConfig = { + region: "us-west-2", + credentials: { + accessKeyId: "AKIAIOSFODNN7EXAMPLE", + secretAccessKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + }, + }; + + describe("constructor", () => { + it("应当使用默认 AWS endpoint 当未指定 endpoint 时", () => { + const client = new S3Client(defaultConfig); + + expect(client.getEndpointUrl()).toBe("https://s3.us-west-2.amazonaws.com"); + expect(client.hasCustomEndpoint()).toBe(false); + }); + + it("应当使用自定义 endpoint", () => { + const client = new S3Client({ + ...defaultConfig, + endpoint: "https://minio.example.com:9000", + }); + + expect(client.getEndpointUrl()).toBe("https://minio.example.com:9000"); + expect(client.hasCustomEndpoint()).toBe(true); + }); + + it("应当为无协议前缀的 endpoint 自动添加 https://", () => { + const client = new S3Client({ + ...defaultConfig, + endpoint: "s3.custom.com", + }); + + expect(client.getEndpointUrl()).toBe("https://s3.custom.com"); + }); + + it("应当去除 endpoint 末尾的斜杠", () => { + const client = new S3Client({ + ...defaultConfig, + endpoint: "https://minio.example.com///", + }); + + expect(client.getEndpointUrl()).toBe("https://minio.example.com"); + }); + + it("应当支持 http:// 协议的 endpoint", () => { + const client = new S3Client({ + ...defaultConfig, + endpoint: "http://localhost:9000", + }); + + expect(client.getEndpointUrl()).toBe("http://localhost:9000"); + }); + + it("应当默认 forcePathStyle 为 true", () => { + const client = new S3Client(defaultConfig); + + expect(client.isForcePathStyle()).toBe(true); + }); + + it("应当允许设置 forcePathStyle 为 false", () => { + const client = new S3Client({ + ...defaultConfig, + forcePathStyle: false, + }); + + expect(client.isForcePathStyle()).toBe(false); + }); + + it("应当正确返回 region", () => { + const client = new S3Client(defaultConfig); + expect(client.getRegion()).toBe("us-west-2"); + }); + + it("应当在 region 为空字符串时默认使用 us-east-1", () => { + const client = new S3Client({ + ...defaultConfig, + region: "", + }); + + expect(client.getRegion()).toBe("us-east-1"); + }); + }); + + // ---- request 方法 ---- + describe("request", () => { + let client: S3Client; + let fetchSpy: ReturnType; + + beforeEach(() => { + client = new S3Client({ + ...defaultConfig, + endpoint: "https://s3.us-west-2.amazonaws.com", + }); + fetchSpy = vi.fn(); + vi.stubGlobal("fetch", fetchSpy); + }); + + afterEach(() => { + vi.unstubAllGlobals(); + }); + + it("应当发送 GET 请求并返回 Response", async () => { + const mockResponse = new Response("hello", { status: 200, statusText: "OK" }); + fetchSpy.mockResolvedValue(mockResponse); + + const resp = await client.request("GET", "my-bucket", "test-key.txt"); + + expect(resp).toBe(mockResponse); + expect(fetchSpy).toHaveBeenCalledTimes(1); + + // 验证 URL(path-style) + const [url, options] = fetchSpy.mock.calls[0]; + expect(url).toContain("/my-bucket/test-key.txt"); + expect(options.method).toBe("GET"); + }); + + it("应当在 path-style 模式下构建正确的 URL", async () => { + fetchSpy.mockResolvedValue(new Response("", { status: 200 })); + + await client.request("GET", "my-bucket", "folder/file.txt"); + + const [url] = fetchSpy.mock.calls[0]; + expect(url).toBe("https://s3.us-west-2.amazonaws.com/my-bucket/folder/file.txt"); + }); + + it("应当在 virtual-hosted 模式下构建正确的 URL", async () => { + const vhClient = new S3Client({ + ...defaultConfig, + forcePathStyle: false, + }); + fetchSpy.mockResolvedValue(new Response("", { status: 200 })); + + await vhClient.request("GET", "my-bucket", "file.txt"); + + const [url] = fetchSpy.mock.calls[0]; + expect(url).toBe("https://my-bucket.s3.us-west-2.amazonaws.com/file.txt"); + }); + + it("应当在请求头中包含 AWS Signature V4 签名", async () => { + fetchSpy.mockResolvedValue(new Response("", { status: 200 })); + + await client.request("GET", "my-bucket", "test.txt"); + + const [, options] = fetchSpy.mock.calls[0]; + const headers = options.headers; + + // 验证签名头存在 + expect(headers["authorization"]).toMatch(/^AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE\//); + expect(headers["authorization"]).toContain("SignedHeaders="); + expect(headers["authorization"]).toContain("Signature="); + expect(headers["x-amz-date"]).toMatch(/^\d{8}T\d{6}Z$/); + expect(headers["x-amz-content-sha256"]).toBeDefined(); + }); + + it("应当正确传递 query parameters", async () => { + fetchSpy.mockResolvedValue(new Response("", { status: 200 })); + + await client.request("GET", "my-bucket", undefined, { + queryParams: { "list-type": "2", prefix: "docs/" }, + }); + + const [url] = fetchSpy.mock.calls[0]; + expect(url).toContain("list-type=2"); + expect(url).toContain("prefix=docs%2F"); + }); + + it("应当正确传递 string body 的 PUT 请求", async () => { + fetchSpy.mockResolvedValue(new Response("", { status: 200 })); + + await client.request("PUT", "my-bucket", "file.txt", { + body: "file content", + headers: { "Content-Type": "text/plain" }, + }); + + const [, options] = fetchSpy.mock.calls[0]; + expect(options.method).toBe("PUT"); + expect(options.body).toBe("file content"); + }); + + it("应当正确传递 Uint8Array body", async () => { + fetchSpy.mockResolvedValue(new Response("", { status: 200 })); + + const body = new TextEncoder().encode("binary data"); + await client.request("PUT", "my-bucket", "binary.bin", { body }); + + const [url, options] = fetchSpy.mock.calls[0]; + expect(url).toContain("/my-bucket/binary.bin"); + expect(options.method).toBe("PUT"); + // body 应当是 Uint8Array.buffer(ArrayBuffer 或兼容类型) + expect(options.body).toBeDefined(); + expect(options.body).not.toBeTypeOf("string"); + }); + + it("应当在非 2xx 响应时抛出 S3Error(XML 错误体)", async () => { + const errorXml = ` + + NoSuchKey + The specified key does not exist. + `; + fetchSpy.mockResolvedValue(new Response(errorXml, { status: 404, statusText: "Not Found" })); + + try { + await client.request("GET", "my-bucket", "nonexistent.txt"); + expect.unreachable("should have thrown"); + } catch (e) { + expect(e).toBeInstanceOf(S3Error); + if (e instanceof S3Error) { + expect(e.code).toBe("NoSuchKey"); + expect(e.statusCode).toBe(404); + expect(e.message).toBe("The specified key does not exist."); + } + } + }); + + it("应当在无 XML 体的错误响应时使用状态码映射", async () => { + fetchSpy.mockResolvedValue(new Response("", { status: 403, statusText: "Forbidden" })); + + await expect(client.request("HEAD", "my-bucket")).rejects.toSatisfy((e: S3Error) => { + return e instanceof S3Error && e.statusCode === 403; + }); + }); + + it("应当在 DELETE 请求成功时返回 Response", async () => { + // jsdom 不支持 204 状态码构造 Response,使用 200 代替验证 DELETE 请求逻辑 + fetchSpy.mockResolvedValue(new Response(null, { status: 200, statusText: "OK" })); + + const resp = await client.request("DELETE", "my-bucket", "file.txt"); + expect(resp.status).toBe(200); + }); + + it("应当不在 fetch headers 中包含 host 头", async () => { + fetchSpy.mockResolvedValue(new Response("", { status: 200 })); + + await client.request("GET", "my-bucket", "test.txt"); + + const [, options] = fetchSpy.mock.calls[0]; + expect(options.headers["host"]).toBeUndefined(); + }); + + it("应当将自定义 headers 的 key 转为小写", async () => { + fetchSpy.mockResolvedValue(new Response("", { status: 200 })); + + await client.request("PUT", "my-bucket", "test.txt", { + body: "data", + headers: { "Content-Type": "text/plain", "X-Custom-Header": "value" }, + }); + + const [, options] = fetchSpy.mock.calls[0]; + // authorization 中 SignedHeaders 应包含小写 key + expect(options.headers["authorization"]).toContain("content-type"); + expect(options.headers["authorization"]).toContain("x-custom-header"); + }); + + it("应当在不传 key 时只使用 bucket 路径", async () => { + fetchSpy.mockResolvedValue(new Response("", { status: 200 })); + + await client.request("HEAD", "my-bucket"); + + const [url] = fetchSpy.mock.calls[0]; + expect(url).toBe("https://s3.us-west-2.amazonaws.com/my-bucket"); + }); + + it("应当正确处理包含特殊字符的 key", async () => { + fetchSpy.mockResolvedValue(new Response("", { status: 200 })); + + await client.request("GET", "my-bucket", "path/to/file with spaces.txt"); + + const [url] = fetchSpy.mock.calls[0]; + expect(url).toContain("file%20with%20spaces.txt"); + }); + }); +}); diff --git a/packages/filesystem/s3/s3.test.ts b/packages/filesystem/s3/s3.test.ts new file mode 100644 index 000000000..c82cc1ebd --- /dev/null +++ b/packages/filesystem/s3/s3.test.ts @@ -0,0 +1,413 @@ +import { describe, it, expect, vi, beforeEach } from "vitest"; +import S3FileSystem from "./s3"; +import { S3Client, S3Error } from "./client"; +import type { FileInfo } from "../filesystem"; + +/** 创建 mock S3Client 实例(通过 prototype 伪装为 S3Client 的实例) */ +function createMockClient(overrides?: Partial): S3Client { + const mock = { + request: vi.fn(), + getEndpointUrl: vi.fn().mockReturnValue("https://s3.us-east-1.amazonaws.com"), + hasCustomEndpoint: vi.fn().mockReturnValue(false), + getRegion: vi.fn().mockReturnValue("us-east-1"), + isForcePathStyle: vi.fn().mockReturnValue(true), + ...overrides, + }; + // 让 instanceof S3Client 检查通过 + Object.setPrototypeOf(mock, S3Client.prototype); + return mock as unknown as S3Client; +} + +/** 创建 mock Response */ +function createMockResponse(options: { + ok?: boolean; + status?: number; + statusText?: string; + text?: string; + blob?: Blob; +}): Response { + const { ok = true, status = 200, statusText = "OK", text = "" } = options; + return { + ok, + status, + statusText, + headers: new Headers(), + text: vi.fn().mockResolvedValue(text), + blob: vi.fn().mockResolvedValue(options.blob ?? new Blob([text])), + } as unknown as Response; +} + +describe("S3FileSystem", () => { + let mockClient: S3Client; + let fs: S3FileSystem; + + beforeEach(() => { + vi.clearAllMocks(); + mockClient = createMockClient(); + fs = new S3FileSystem("test-bucket", mockClient); + }); + + // ---- verify ---- + describe("verify", () => { + it("应当成功验证 bucket", async () => { + (mockClient.request as ReturnType).mockResolvedValue(createMockResponse({ ok: true })); + + await expect(fs.verify()).resolves.toBeUndefined(); + expect(mockClient.request).toHaveBeenCalledWith("HEAD", "test-bucket"); + }); + + it("应当在 bucket 不存在时抛出 NotFound 错误", async () => { + (mockClient.request as ReturnType).mockRejectedValue( + new S3Error("NoSuchBucket", "The specified bucket does not exist", 404) + ); + + await expect(fs.verify()).rejects.toThrow("NotFound"); + }); + + it("应当在 404 状态码时抛出 NotFound 错误", async () => { + (mockClient.request as ReturnType).mockRejectedValue(new S3Error("NotFound", "Not Found", 404)); + + await expect(fs.verify()).rejects.toThrow("NotFound"); + }); + + it("应当在认证失败时抛出 WarpTokenError", async () => { + (mockClient.request as ReturnType).mockRejectedValue( + new S3Error("InvalidAccessKeyId", "The AWS Access Key Id you provided does not exist", 403) + ); + + await expect(fs.verify()).rejects.toMatchObject({ + error: expect.any(S3Error), + }); + }); + + it("应当在 SignatureDoesNotMatch 时抛出 WarpTokenError", async () => { + (mockClient.request as ReturnType).mockRejectedValue( + new S3Error("SignatureDoesNotMatch", "Signature does not match", 403) + ); + + await expect(fs.verify()).rejects.toMatchObject({ + error: expect.any(S3Error), + }); + }); + + it("应当在 AccessDenied 时抛出 Access Denied 错误", async () => { + (mockClient.request as ReturnType).mockRejectedValue( + new S3Error("AccessDenied", "Access Denied", 403) + ); + + await expect(fs.verify()).rejects.toThrow("Access Denied"); + }); + + it("应当在 PermanentRedirect (301) 时抛出 Access Denied 错误", async () => { + (mockClient.request as ReturnType).mockRejectedValue( + new S3Error("PermanentRedirect", "Permanent Redirect", 301) + ); + + await expect(fs.verify()).rejects.toThrow("Access Denied"); + }); + + it("应当在网络错误时抛出网络连接失败错误", async () => { + const networkError = new Error("fetch failed"); + (mockClient.request as ReturnType).mockRejectedValue(networkError); + + await expect(fs.verify()).rejects.toThrow("Network connection failed"); + }); + + it("应当将未知错误原样抛出", async () => { + const unknownError = new Error("unknown error"); + (mockClient.request as ReturnType).mockRejectedValue(unknownError); + + await expect(fs.verify()).rejects.toThrow("unknown error"); + }); + }); + + // ---- open ---- + describe("open", () => { + it("应当返回 S3FileReader", async () => { + const fileInfo: FileInfo = { + name: "test.txt", + path: "/docs", + size: 100, + digest: "abc", + createtime: 1000, + updatetime: 2000, + }; + const reader = await fs.open(fileInfo); + + expect(reader).toBeDefined(); + expect(reader.read).toBeTypeOf("function"); + }); + + it("S3FileReader.read 应调用 client.request GET", async () => { + const fileInfo: FileInfo = { + name: "hello.txt", + path: "/data", + size: 50, + digest: "xyz", + createtime: 1000, + updatetime: 2000, + }; + (mockClient.request as ReturnType).mockResolvedValue(createMockResponse({ text: "file content" })); + + const reader = await fs.open(fileInfo); + const content = await reader.read("string"); + + expect(mockClient.request).toHaveBeenCalledWith("GET", "test-bucket", "data/hello.txt"); + expect(content).toBe("file content"); + }); + }); + + // ---- create ---- + describe("create", () => { + it("应当返回 S3FileWriter", async () => { + const writer = await fs.create("test.txt"); + + expect(writer).toBeDefined(); + expect(writer.write).toBeTypeOf("function"); + }); + + it("S3FileWriter.write 应调用 client.request PUT", async () => { + (mockClient.request as ReturnType).mockResolvedValue(createMockResponse({ ok: true })); + + const writer = await fs.create("output.txt"); + await writer.write("hello world"); + + expect(mockClient.request).toHaveBeenCalledWith( + "PUT", + "test-bucket", + "output.txt", + expect.objectContaining({ + body: "hello world", + headers: expect.objectContaining({ + "content-type": "application/octet-stream", + }), + }) + ); + }); + }); + + // ---- createDir ---- + describe("createDir", () => { + it("应当静默成功(S3 中目录是隐式的)", async () => { + await expect(fs.createDir("new-dir")).resolves.toBeUndefined(); + }); + }); + + // ---- delete ---- + describe("delete", () => { + it("应当成功删除文件", async () => { + (mockClient.request as ReturnType).mockResolvedValue(createMockResponse({ ok: true, status: 204 })); + + await expect(fs.delete("test.txt")).resolves.toBeUndefined(); + expect(mockClient.request).toHaveBeenCalledWith("DELETE", "test-bucket", "test.txt"); + }); + + it("应当在 NoSuchKey 时静默成功(幂等删除)", async () => { + (mockClient.request as ReturnType).mockRejectedValue( + new S3Error("NoSuchKey", "The specified key does not exist", 404) + ); + + await expect(fs.delete("nonexistent.txt")).resolves.toBeUndefined(); + }); + + it("应当在其它 S3 错误时抛出异常", async () => { + (mockClient.request as ReturnType).mockRejectedValue( + new S3Error("AccessDenied", "Access Denied", 403) + ); + + await expect(fs.delete("test.txt")).rejects.toThrow(); + }); + }); + + // ---- list ---- + describe("list", () => { + it("应当列出当前目录下的文件", async () => { + const xml = ` + + false + + file1.txt + 2024-01-01T00:00:00.000Z + "abc123" + 1024 + + + file2.txt + 2024-01-02T00:00:00.000Z + "def456" + 2048 + + `; + + (mockClient.request as ReturnType).mockResolvedValue(createMockResponse({ text: xml })); + + const files = await fs.list(); + + expect(files).toHaveLength(2); + expect(files[0]).toMatchObject({ + name: "file1.txt", + path: "/", + size: 1024, + digest: "abc123", + }); + expect(files[1]).toMatchObject({ + name: "file2.txt", + path: "/", + size: 2048, + digest: "def456", + }); + }); + + it("应当正确处理带 basePath 的目录列表", async () => { + const subFs = new S3FileSystem("test-bucket", mockClient, "/docs"); + + const xml = ` + + false + + docs/readme.md + 2024-06-15T12:00:00.000Z + "aaa" + 512 + + `; + + (mockClient.request as ReturnType).mockResolvedValue(createMockResponse({ text: xml })); + + const files = await subFs.list(); + + expect(files).toHaveLength(1); + expect(files[0]).toMatchObject({ + name: "readme.md", + path: "/docs", + size: 512, + }); + }); + + it("应当跳过目录占位符(以 / 结尾的 key)", async () => { + const xml = ` + + false + + subdir/ + 2024-01-01T00:00:00.000Z + "" + 0 + + + file.txt + 2024-01-01T00:00:00.000Z + "xyz" + 100 + + `; + + (mockClient.request as ReturnType).mockResolvedValue(createMockResponse({ text: xml })); + + const files = await fs.list(); + + expect(files).toHaveLength(1); + expect(files[0].name).toBe("file.txt"); + }); + + it("应当处理分页(isTruncated + continuationToken)", async () => { + const xmlPage1 = ` + + true + token123 + + file1.txt + 2024-01-01T00:00:00.000Z + "aaa" + 100 + + `; + + const xmlPage2 = ` + + false + + file2.txt + 2024-01-02T00:00:00.000Z + "bbb" + 200 + + `; + + (mockClient.request as ReturnType) + .mockResolvedValueOnce(createMockResponse({ text: xmlPage1 })) + .mockResolvedValueOnce(createMockResponse({ text: xmlPage2 })); + + const files = await fs.list(); + + expect(files).toHaveLength(2); + expect(files[0].name).toBe("file1.txt"); + expect(files[1].name).toBe("file2.txt"); + expect(mockClient.request).toHaveBeenCalledTimes(2); + }); + + it("应当返回空数组当目录为空时", async () => { + const xml = ` + + false + `; + + (mockClient.request as ReturnType).mockResolvedValue(createMockResponse({ text: xml })); + + const files = await fs.list(); + expect(files).toHaveLength(0); + }); + + it("应当在 AccessDenied 时抛出权限错误", async () => { + (mockClient.request as ReturnType).mockRejectedValue( + new S3Error("AccessDenied", "Access Denied", 403) + ); + + await expect(fs.list()).rejects.toThrow("Permission denied"); + }); + }); + + // ---- openDir ---- + describe("openDir", () => { + it("应当返回新的 S3FileSystem 实例并拼接路径", async () => { + const subFs = (await fs.openDir("subdir")) as S3FileSystem; + + expect(subFs).toBeInstanceOf(S3FileSystem); + expect(subFs.bucket).toBe("test-bucket"); + expect(subFs.basePath).toBe("/subdir"); + }); + + it("应当支持嵌套 openDir", async () => { + const sub1 = (await fs.openDir("a")) as S3FileSystem; + const sub2 = (await sub1.openDir("b")) as S3FileSystem; + + expect(sub2.basePath).toBe("/a/b"); + }); + }); + + // ---- getDirUrl ---- + describe("getDirUrl", () => { + it("自定义 endpoint 应当返回 endpoint + bucket/prefix 路径", async () => { + const customClient = createMockClient({ + hasCustomEndpoint: vi.fn().mockReturnValue(true), + getEndpointUrl: vi.fn().mockReturnValue("https://minio.example.com"), + }); + const customFs = new S3FileSystem("my-bucket", customClient, "/data"); + + const url = await customFs.getDirUrl(); + expect(url).toBe("https://minio.example.com/my-bucket/data"); + }); + + it("AWS S3 应当返回控制台 URL", async () => { + const url = await fs.getDirUrl(); + expect(url).toContain("s3.console.aws.amazon.com"); + expect(url).toContain("test-bucket"); + expect(url).toContain("us-east-1"); + }); + + it("根目录时 prefix 应为空", async () => { + const url = await fs.getDirUrl(); + expect(url).toContain("prefix=&"); + }); + }); +});