diff --git a/packages/global/package.json b/packages/global/package.json index 9cec61e63..6c327f2e6 100644 --- a/packages/global/package.json +++ b/packages/global/package.json @@ -2,7 +2,7 @@ "name": "@fastgpt/global", "version": "1.0.0", "dependencies": { - "@fastgpt-sdk/plugin": "0.2.16", + "@fastgpt-sdk/plugin": "0.2.17", "@apidevtools/swagger-parser": "^10.1.0", "@bany/curl-to-json": "^1.2.8", "axios": "^1.12.1", diff --git a/packages/service/common/s3/buckets/base.ts b/packages/service/common/s3/buckets/base.ts index 2ab81c923..1afab82a0 100644 --- a/packages/service/common/s3/buckets/base.ts +++ b/packages/service/common/s3/buckets/base.ts @@ -10,18 +10,17 @@ import { type CreatePostPresignedUrlOptions, type CreatePostPresignedUrlParams, type CreatePostPresignedUrlResult, - type S3OptionsType, type createPreviewUrlParams, CreateGetPresignedUrlParamsSchema } from '../type'; -import { defaultS3Options, getSystemMaxFileSize, Mimes } from '../constants'; +import { getSystemMaxFileSize, Mimes } from '../constants'; import path from 'node:path'; import { MongoS3TTL } from '../schema'; -import { addHours, addMinutes } from 'date-fns'; +import { addHours, addMinutes, differenceInSeconds } from 'date-fns'; import { addLog } from '../../system/log'; import { addS3DelJob } from '../mq'; -import { type Readable } from 'node:stream'; import { type UploadFileByBufferParams, UploadFileByBufferSchema } from '../type'; +import { type IStorage } from '@fastgpt-sdk/storage'; import { parseFileExtensionFromUrl } from '@fastgpt/global/common/string/tools'; // Check if the error is a "file not found" type error, which should be treated as success @@ -45,82 +44,26 @@ export const isFileNotFoundError = (error: any): boolean => { }; export class S3BaseBucket { - private _client: Client; - private _externalClient: Client | undefined; - - /** - * - * @param bucketName the bucket you want to operate - * @param options the options for the s3 client - */ constructor( - public readonly bucketName: string, - public options: Partial = defaultS3Options - ) { - options = { ...defaultS3Options, ...options }; - this.options = options; - this._client = new Client(options as S3OptionsType); + private readonly _client: IStorage, + private readonly _externalClient: IStorage | undefined + ) {} - if (this.options.externalBaseURL) { - const externalBaseURL = new URL(this.options.externalBaseURL); - const endpoint = externalBaseURL.hostname; - const useSSL = externalBaseURL.protocol === 'https:'; - - const externalPort = externalBaseURL.port - ? parseInt(externalBaseURL.port) - : useSSL - ? 443 - : undefined; // https 默认 443,其他情况让 MinIO 客户端使用默认端口 - - this._externalClient = new Client({ - useSSL: useSSL, - endPoint: endpoint, - port: externalPort, - accessKey: options.accessKey, - secretKey: options.secretKey, - pathStyle: options.pathStyle, - region: options.region - }); - } - - const init = async () => { - // Not exists bucket, create it - if (!(await this.client.bucketExists(this.bucketName))) { - await this.client.makeBucket(this.bucketName); - } - await this.options.afterInit?.(); - console.log(`S3 init success: ${this.bucketName}`); - }; - if (this.options.init) { - init(); - } - } - - get client(): Client { + get client(): IStorage { return this._client; } - get externalClient(): Client { + + get externalClient(): IStorage { return this._externalClient ?? this._client; } + get bucketName(): string { + return this.client.bucketName; + } + // TODO: 加到 MQ 里保障幂等 - async move({ - from, - to, - options - }: { - from: string; - to: string; - options?: CopyConditions; - }): Promise { - await this.copy({ - from, - to, - options: { - copyConditions: options, - temporary: false - } - }); + async move({ from, to }: { from: string; to: string }): Promise { + await this.copy({ from, to, options: { temporary: false } }); await this.removeObject(from); } @@ -133,10 +76,8 @@ export class S3BaseBucket { to: string; options?: { temporary?: boolean; - copyConditions?: CopyConditions; }; - }): ReturnType { - const bucket = this.bucketName; + }) { if (options?.temporary) { await MongoS3TTL.create({ minioKey: to, @@ -144,11 +85,11 @@ export class S3BaseBucket { expiredTime: addHours(new Date(), 24) }); } - return this.client.copyObject(bucket, to, `${bucket}/${from}`, options?.copyConditions); + return this.client.copyObjectInSelfBucket({ sourceKey: from, targetKey: to }); } - async removeObject(objectKey: string, options?: RemoveOptions): Promise { - return this.client.removeObject(this.bucketName, objectKey, options).catch((err) => { + async removeObject(objectKey: string): Promise { + this.client.deleteObject({ key: objectKey }).catch((err) => { if (isFileNotFoundError(err)) { return Promise.resolve(); } @@ -160,66 +101,17 @@ export class S3BaseBucket { }); } - // 列出文件 - listObjectsV2( - ...params: Parameters extends [string, ...infer R] ? R : never - ) { - return this.client.listObjectsV2(this.bucketName, ...params); - } - - // 上传文件 - putObject(...params: Parameters extends [string, ...infer R] ? R : never) { - return this.client.putObject(this.bucketName, ...params); - } - - // 获取文件流 - getFileStream( - ...params: Parameters extends [string, ...infer R] ? R : never - ) { - return this.client.getObject(this.bucketName, ...params); - } - - // 获取文件状态 - async statObject( - ...params: Parameters extends [string, ...infer R] ? R : never - ) { - try { - return await this.client.statObject(this.bucketName, ...params); - } catch (error) { - if (error instanceof S3Error && error.message === 'Not Found') { - return null; - } - return Promise.reject(error); - } - } - - // 判断文件是否存在 - async isObjectExists(key: string): Promise { - try { - await this.client.statObject(this.bucketName, key); - return true; - } catch (err) { - if (err instanceof S3Error && err.message === 'Not Found') { - return false; - } - return Promise.reject(err); - } - } - - // 将文件流转换为Buffer - async fileStreamToBuffer(stream: Readable): Promise { - const chunks: Buffer[] = []; - for await (const chunk of stream) { - chunks.push(chunk); - } - return Buffer.concat(chunks); - } - addDeleteJob(params: Omit[0], 'bucketName'>) { return addS3DelJob({ ...params, bucketName: this.bucketName }); } - async createPostPresignedUrl( + async isObjectExists(key: string) { + const { exists } = await this.client.checkObjectExists({ key }); + + return exists ?? false; + } + + async createPresignedPutUrl( params: CreatePostPresignedUrlParams, options: CreatePostPresignedUrlOptions = {} ): Promise { @@ -229,42 +121,39 @@ export class S3BaseBucket { const filename = params.filename; const ext = path.extname(filename).toLowerCase(); const contentType = Mimes[ext as keyof typeof Mimes] ?? 'application/octet-stream'; + const expiredSeconds = differenceInSeconds(addMinutes(new Date(), 10), new Date()); - const key = params.rawKey; - - const policy = this.externalClient.newPostPolicy(); - policy.setKey(key); - policy.setBucket(this.bucketName); - policy.setContentType(contentType); - if (formatMaxFileSize) { - policy.setContentLengthRange(1, formatMaxFileSize); - } - policy.setExpires(addMinutes(new Date(), 10)); - policy.setUserMetaData({ - 'content-disposition': `attachment; filename="${encodeURIComponent(filename)}"`, - 'origin-filename': encodeURIComponent(filename), - 'upload-time': new Date().toISOString(), - ...params.metadata + const { metadata, putUrl } = await this.externalClient.generatePresignedPutUrl({ + key: params.rawKey, + expiredSeconds, + contentType, + metadata: { + contentDisposition: `attachment; filename="${encodeURIComponent(filename)}"`, + originFilename: encodeURIComponent(filename), + uploadTime: new Date().toISOString(), + ...params.metadata + } }); - const { formData, postURL } = await this.externalClient.presignedPostPolicy(policy); - if (expiredHours) { await MongoS3TTL.create({ - minioKey: key, + minioKey: params.rawKey, bucketName: this.bucketName, expiredTime: addHours(new Date(), expiredHours) }); } return { - url: postURL, - fields: formData, + url: putUrl, + fields: { + ...metadata, + key: params.rawKey + }, maxSize: formatMaxFileSize }; } catch (error) { - addLog.error('Failed to create post presigned url', error); - return Promise.reject('Failed to create post presigned url'); + addLog.error('Failed to create presigned put url', error); + return Promise.reject('Failed to create presigned put url'); } } @@ -274,7 +163,7 @@ export class S3BaseBucket { const { key, expiredHours } = parsed; const expires = expiredHours ? expiredHours * 60 * 60 : 30 * 60; // expires 的单位是秒 默认 30 分钟 - return await this.externalClient.presignedGetObject(this.bucketName, key, expires); + return await this.externalClient.generatePresignedGetUrl({ key, expiredSeconds: expires }); } async createPreviewUrl(params: createPreviewUrlParams) { @@ -283,7 +172,7 @@ export class S3BaseBucket { const { key, expiredHours } = parsed; const expires = expiredHours ? expiredHours * 60 * 60 : 30 * 60; // expires 的单位是秒 默认 30 分钟 - return await this.client.presignedGetObject(this.bucketName, key, expires); + return await this.client.generatePresignedGetUrl({ key, expiredSeconds: expires }); } async uploadFileByBuffer(params: UploadFileByBufferParams) { @@ -294,8 +183,11 @@ export class S3BaseBucket { bucketName: this.bucketName, expiredTime: addHours(new Date(), 1) }); - await this.putObject(key, buffer, undefined, { - 'Content-Type': contentType || 'application/octet-stream' + + await this.client.uploadObject({ + key, + body: buffer, + contentType: contentType || 'application/octet-stream' }); return { @@ -307,16 +199,15 @@ export class S3BaseBucket { }; } - // 对外包装的方法 - // 获取文件元数据 async getFileMetadata(key: string) { - const stat = await this.statObject(key); - if (!stat) return; + const metadataResponse = await this.client.getObjectMetadata({ key }); + if (!metadataResponse) return; - const contentLength = stat.size; - const filename: string = decodeURIComponent(stat.metaData['origin-filename']); + const contentLength = metadataResponse.contentLength; + const filename: string = decodeURIComponent(metadataResponse.metadata.originFilename || ''); const extension = parseFileExtensionFromUrl(filename); - const contentType: string = stat.metaData['content-type']; + const contentType: string = metadataResponse.contentType || 'application/octet-stream'; + return { filename, extension, @@ -324,4 +215,11 @@ export class S3BaseBucket { contentLength }; } + + async getFileStream(key: string) { + const downloadResponse = await this.client.downloadObject({ key }); + if (!downloadResponse) return; + + return downloadResponse.body; + } } diff --git a/packages/service/common/s3/buckets/private.ts b/packages/service/common/s3/buckets/private.ts index 1d85712f7..1bb744585 100644 --- a/packages/service/common/s3/buckets/private.ts +++ b/packages/service/common/s3/buckets/private.ts @@ -1,9 +1,80 @@ import { S3BaseBucket } from './base'; -import { S3Buckets } from '../constants'; -import { type S3OptionsType } from '../type'; +import { createDefaultStorageOptions } from '../constants'; +import { + type IAwsS3CompatibleStorageOptions, + createStorage, + type ICosStorageOptions, + type IOssStorageOptions, + type IStorage +} from '@fastgpt-sdk/storage'; export class S3PrivateBucket extends S3BaseBucket { - constructor(options?: Partial) { - super(S3Buckets.private, options); + constructor() { + const { vendor, privateBucket, externalBaseUrl, credentials, region, ...options } = + createDefaultStorageOptions(); + + let config: any = {}; + let externalConfig: any = {}; + if (vendor === 'minio') { + config = { + region, + vendor, + credentials, + forcePathStyle: true, + endpoint: options.endpoint!, + maxRetries: options.maxRetries! + } as Omit; + externalConfig = { + ...config, + endpoint: externalBaseUrl + }; + } else if (vendor === 'aws-s3') { + config = { + region, + vendor, + credentials, + endpoint: options.endpoint!, + maxRetries: options.maxRetries! + } as Omit; + externalConfig = { + ...config, + endpoint: externalBaseUrl + }; + } else if (vendor === 'cos') { + config = { + region, + vendor, + credentials, + proxy: options.proxy, + domain: options.domain, + protocol: options.protocol, + useAccelerate: options.useAccelerate + } as Omit; + } else if (vendor === 'oss') { + config = { + region, + vendor, + credentials, + endpoint: options.endpoint!, + cname: options.cname, + internal: options.internal, + secure: options.secure, + enableProxy: options.enableProxy + } as Omit; + } + + const client = createStorage({ bucket: privateBucket, ...config }); + + let externalClient: IStorage | undefined = undefined; + if (externalBaseUrl) { + externalClient = createStorage({ bucket: privateBucket, ...externalConfig }); + } + + super(client, externalClient); + + client.ensureBucket(); + if (externalClient) { + externalClient.ensureBucket(); + } } } diff --git a/packages/service/common/s3/buckets/public.ts b/packages/service/common/s3/buckets/public.ts index 331c79277..a8932914c 100644 --- a/packages/service/common/s3/buckets/public.ts +++ b/packages/service/common/s3/buckets/public.ts @@ -1,51 +1,92 @@ import { S3BaseBucket } from './base'; -import { S3Buckets } from '../constants'; -import { type S3OptionsType } from '../type'; +import { createDefaultStorageOptions } from '../constants'; +import { + type IAwsS3CompatibleStorageOptions, + type ICosStorageOptions, + type IOssStorageOptions, + createStorage, + type IStorage, + type MinioStorageAdapter +} from '@fastgpt-sdk/storage'; export class S3PublicBucket extends S3BaseBucket { - constructor(options?: Partial) { - super(S3Buckets.public, { - ...options, - afterInit: async () => { - const bucket = this.bucketName; - const policy = JSON.stringify({ - Version: '2012-10-17', - Statement: [ - { - Effect: 'Allow', - Principal: '*', - Action: 's3:GetObject', - Resource: `arn:aws:s3:::${bucket}/*` - } - ] - }); - try { - await this.client.setBucketPolicy(bucket, policy); - } catch (error) { - // NOTE: maybe it was a cloud S3 that doesn't allow us to set the policy, so that cause the error, - // maybe we can ignore the error, or we have other plan to handle this. - console.error('Failed to set bucket policy:', error); - } - } + constructor() { + const { vendor, publicBucket, externalBaseUrl, credentials, region, ...options } = + createDefaultStorageOptions(); + + let config: any = {}; + let externalConfig: any = {}; + if (vendor === 'minio') { + config = { + region, + vendor, + credentials, + forcePathStyle: true, + endpoint: options.endpoint!, + maxRetries: options.maxRetries! + } as Omit; + externalConfig = { + ...config, + endpoint: externalBaseUrl + }; + } else if (vendor === 'aws-s3') { + config = { + region, + vendor, + credentials, + endpoint: options.endpoint!, + maxRetries: options.maxRetries! + } as Omit; + externalConfig = { + ...config, + endpoint: externalBaseUrl + }; + } else if (vendor === 'cos') { + config = { + region, + vendor, + credentials, + proxy: options.proxy, + domain: options.domain, + protocol: options.protocol, + useAccelerate: options.useAccelerate + } as Omit; + } else if (vendor === 'oss') { + config = { + region, + vendor, + credentials, + endpoint: options.endpoint!, + cname: options.cname, + internal: options.internal, + secure: options.secure, + enableProxy: options.enableProxy + } as Omit; + } + + const client = createStorage({ bucket: publicBucket, ...config }); + + let externalClient: IStorage | undefined = undefined; + if (externalBaseUrl) { + externalClient = createStorage({ bucket: publicBucket, ...externalConfig }); + } + + super(client, externalClient); + + client.ensureBucket().then(() => { + if (vendor !== 'minio') return; + (client as MinioStorageAdapter).ensurePublicBucketPolicy(); }); + + if (externalClient) { + externalClient.ensureBucket().then(() => { + if (vendor !== 'minio') return; + (externalClient as MinioStorageAdapter).ensurePublicBucketPolicy(); + }); + } } createPublicUrl(objectKey: string): string { - const protocol = this.options.useSSL ? 'https' : 'http'; - const hostname = this.options.endPoint; - const port = this.options.port; - const bucket = this.bucketName; - - const url = new URL(`${protocol}://${hostname}:${port}/${bucket}/${objectKey}`); - - if (this.options.externalBaseURL) { - const externalBaseURL = new URL(this.options.externalBaseURL); - - url.port = externalBaseURL.port; - url.hostname = externalBaseURL.hostname; - url.protocol = externalBaseURL.protocol; - } - - return url.toString(); + return this.externalClient.generatePublicGetUrl({ key: objectKey }).publicGetUrl; } } diff --git a/packages/service/common/s3/constants.ts b/packages/service/common/s3/constants.ts index 03e1853e8..708677d7b 100644 --- a/packages/service/common/s3/constants.ts +++ b/packages/service/common/s3/constants.ts @@ -1,6 +1,9 @@ -import { HttpProxyAgent } from 'http-proxy-agent'; -import { HttpsProxyAgent } from 'https-proxy-agent'; -import type { ClientOptions } from 'minio'; +import type { + IAwsS3CompatibleStorageOptions, + ICosStorageOptions, + IOssStorageOptions, + IStorageOptions +} from '@fastgpt-sdk/storage'; export const Mimes = { '.gif': 'image/gif', @@ -25,24 +28,9 @@ export const Mimes = { '.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation' } as const; -export const defaultS3Options: { - externalBaseURL?: string; - afterInit?: () => Promise | void; - init?: boolean; -} & ClientOptions = { - useSSL: process.env.S3_USE_SSL === 'true', - endPoint: process.env.S3_ENDPOINT || 'localhost', - externalBaseURL: process.env.S3_EXTERNAL_BASE_URL, - accessKey: process.env.S3_ACCESS_KEY || 'minioadmin', - secretKey: process.env.S3_SECRET_KEY || 'minioadmin', - port: process.env.S3_PORT ? parseInt(process.env.S3_PORT) : 9000, - pathStyle: process.env.S3_PATH_STYLE === 'false' ? false : true, - region: process.env.S3_REGION || undefined -}; - export const S3Buckets = { - public: process.env.S3_PUBLIC_BUCKET || 'fastgpt-public', - private: process.env.S3_PRIVATE_BUCKET || 'fastgpt-private' + public: process.env.STORAGE_PUBLIC_BUCKET || 'fastgpt-public', + private: process.env.STORAGE_PRIVATE_BUCKET || 'fastgpt-private' } as const; export const getSystemMaxFileSize = () => { @@ -51,3 +39,104 @@ export const getSystemMaxFileSize = () => { }; export const S3_KEY_PATH_INVALID_CHARS = /[|\\/]/; + +export function createDefaultStorageOptions() { + const vendor = (process.env.STORAGE_VENDOR || 'minio') as IStorageOptions['vendor']; + + switch (vendor) { + case 'minio': { + return { + vendor: 'minio', + forcePathStyle: true, + externalBaseUrl: process.env.STORAGE_EXTERNAL_BASE_URL || undefined, + endpoint: process.env.STORAGE_S3_ENDPOINT || 'http://localhost:9000', + region: process.env.STORAGE_REGION || 'us-east-1', + publicBucket: process.env.STORAGE_PUBLIC_BUCKET || 'fastgpt-public', + privateBucket: process.env.STORAGE_PRIVATE_BUCKET || 'fastgpt-private', + credentials: { + accessKeyId: process.env.STORAGE_ACCESS_KEY_ID || 'minioadmin', + secretAccessKey: process.env.STORAGE_SECRET_ACCESS_KEY || 'minioadmin' + }, + maxRetries: process.env.STORAGE_S3_MAX_RETRIES + ? parseInt(process.env.STORAGE_S3_MAX_RETRIES) + : 3 + } satisfies Omit & { + publicBucket: string; + privateBucket: string; + externalBaseUrl?: string; + }; + } + + case 'aws-s3': { + return { + vendor: 'aws-s3', + forcePathStyle: process.env.STORAGE_S3_FORCE_PATH_STYLE === 'true' ? true : false, + externalBaseUrl: process.env.STORAGE_EXTERNAL_BASE_URL || undefined, + endpoint: process.env.STORAGE_S3_ENDPOINT || '', + region: process.env.STORAGE_REGION || 'us-east-1', + publicBucket: process.env.STORAGE_PUBLIC_BUCKET || 'fastgpt-public', + privateBucket: process.env.STORAGE_PRIVATE_BUCKET || 'fastgpt-private', + credentials: { + accessKeyId: process.env.STORAGE_ACCESS_KEY_ID || '', + secretAccessKey: process.env.STORAGE_SECRET_ACCESS_KEY || '' + }, + maxRetries: process.env.STORAGE_S3_MAX_RETRIES + ? parseInt(process.env.STORAGE_S3_MAX_RETRIES) + : 3 + } satisfies Omit & { + publicBucket: string; + privateBucket: string; + externalBaseUrl?: string; + }; + } + + case 'cos': { + return { + vendor: 'cos', + externalBaseUrl: process.env.STORAGE_EXTERNAL_BASE_URL || undefined, + region: process.env.STORAGE_REGION || 'ap-shanghai', + publicBucket: process.env.STORAGE_PUBLIC_BUCKET || 'fastgpt-public', + privateBucket: process.env.STORAGE_PRIVATE_BUCKET || 'fastgpt-private', + credentials: { + accessKeyId: process.env.STORAGE_ACCESS_KEY_ID || '', + secretAccessKey: process.env.STORAGE_SECRET_ACCESS_KEY || '' + }, + protocol: (process.env.STORAGE_COS_PROTOCOL as 'https:' | 'http:' | undefined) || 'https:', + useAccelerate: process.env.STORAGE_COS_USE_ACCELERATE === 'true' ? true : false, + domain: process.env.STORAGE_COS_CNAME_DOMAIN || undefined, + proxy: process.env.STORAGE_COS_PROXY || undefined + } satisfies Omit & { + publicBucket: string; + privateBucket: string; + externalBaseUrl?: string; + }; + } + + case 'oss': { + return { + vendor: 'oss', + externalBaseUrl: process.env.STORAGE_EXTERNAL_BASE_URL || undefined, + endpoint: process.env.STORAGE_OSS_ENDPOINT || '', + region: process.env.STORAGE_REGION || 'oss-cn-hangzhou', + publicBucket: process.env.STORAGE_PUBLIC_BUCKET || 'fastgpt-public', + privateBucket: process.env.STORAGE_PRIVATE_BUCKET || 'fastgpt-private', + credentials: { + accessKeyId: process.env.STORAGE_ACCESS_KEY_ID || '', + secretAccessKey: process.env.STORAGE_SECRET_ACCESS_KEY || '' + }, + cname: process.env.STORAGE_OSS_CNAME === 'true' ? true : false, + internal: process.env.STORAGE_OSS_INTERNAL === 'true' ? true : false, + secure: process.env.STORAGE_OSS_SECURE === 'true' ? true : false, + enableProxy: process.env.STORAGE_OSS_ENABLE_PROXY === 'false' ? false : true + } satisfies Omit & { + publicBucket: string; + privateBucket: string; + externalBaseUrl?: string; + }; + } + + default: { + throw new Error(`Unsupported storage vendor: ${vendor}`); + } + } +} diff --git a/packages/service/common/s3/index.ts b/packages/service/common/s3/index.ts index 72e4c3c92..821d3dcab 100644 --- a/packages/service/common/s3/index.ts +++ b/packages/service/common/s3/index.ts @@ -4,8 +4,8 @@ import { addLog } from '../system/log'; import { startS3DelWorker } from './mq'; export function initS3Buckets() { - const publicBucket = new S3PublicBucket({ init: true }); - const privateBucket = new S3PrivateBucket({ init: true }); + const publicBucket = new S3PublicBucket(); + const privateBucket = new S3PrivateBucket(); global.s3BucketMap = { [publicBucket.bucketName]: publicBucket, diff --git a/packages/service/common/s3/mq.ts b/packages/service/common/s3/mq.ts index 7025bcff0..26a51dc7a 100644 --- a/packages/service/common/s3/mq.ts +++ b/packages/service/common/s3/mq.ts @@ -1,8 +1,8 @@ import { getQueue, getWorker, QueueNames } from '../bullmq'; import { addLog } from '../system/log'; import path from 'path'; -import { batchRun } from '@fastgpt/global/common/system/utils'; -import { isFileNotFoundError, type S3BaseBucket } from './buckets/base'; +import { batchRun, retryFn } from '@fastgpt/global/common/system/utils'; +import pLimit from 'p-limit'; export type S3MQJobData = { key?: string; @@ -23,6 +23,7 @@ const jobOption = { type: 'exponential' } }; + export const addS3DelJob = async (data: S3MQJobData): Promise => { const queue = getQueue(QueueNames.s3FileDelete); const jobId = (() => { @@ -40,77 +41,15 @@ export const addS3DelJob = async (data: S3MQJobData): Promise => { await queue.add('delete-s3-files', data, { jobId, ...jobOption }); }; -export const prefixDel = async (bucket: S3BaseBucket, prefix: string) => { - addLog.debug(`[S3 delete] delete prefix: ${prefix}`); - let tasks: Promise[] = []; - return new Promise((resolve, reject) => { - let timer: NodeJS.Timeout; - const stream = bucket.listObjectsV2(prefix, true); - - let settled = false; - const finish = (error?: any) => { - if (settled) return; - settled = true; - - if (timer) { - clearTimeout(timer); - } - - stream?.removeAllListeners?.(); - stream?.destroy?.(); - - if (error) { - addLog.error(`[S3 delete] delete prefix failed`, error); - reject(error); - } else { - resolve(); - } - }; - - // stream 可能会中断,没有触发 end 和 error,导致 promise 不返回,需要增加定时器兜底。 - timer = setTimeout(() => { - addLog.error(`[S3 delete] delete prefix timeout: ${prefix}`); - finish('Timeout'); - }, 60000); - - stream.on('data', (file) => { - if (!file.name) return; - tasks.push(bucket.removeObject(file.name)); - }); - stream.on('end', async () => { - if (tasks.length === 0) { - return finish(); - } - - if (timer) { - clearTimeout(timer); - } - const results = await Promise.allSettled(tasks); - const failed = results.some((r) => r.status === 'rejected'); - if (failed) { - return finish('Some deletes failed'); - } - finish(); - }); - stream.on('error', (err) => { - if (isFileNotFoundError(err)) { - return finish(); - } - addLog.error(`[S3 delete] delete prefix: ${prefix} error`, err); - return finish(err); - }); - stream.on('pause', () => { - addLog.warn(`[S3 delete] delete prefix: ${prefix} paused`); - stream.resume(); - }); - }); -}; export const startS3DelWorker = async () => { + const limit = pLimit(50); + return getWorker( QueueNames.s3FileDelete, async (job) => { let { prefix, bucketName, key, keys } = job.data; const bucket = global.s3BucketMap[bucketName]; + if (!bucket) { addLog.error(`Bucket not found: ${bucketName}`); return; @@ -121,17 +60,20 @@ export const startS3DelWorker = async () => { } if (keys) { addLog.debug(`[S3 delete] delete keys: ${keys.length}`); + await bucket.client.deleteObjectsByMultiKeys({ keys }); await batchRun(keys, async (key) => { - await bucket.removeObject(key); - // Delete parsed - if (!key.includes('-parsed/')) { - const fileParsedPrefix = `${path.dirname(key)}/${path.basename(key, path.extname(key))}-parsed`; - await prefixDel(bucket, fileParsedPrefix); - } + if (key.includes('-parsed/')) return; + const fileParsedPrefix = `${path.dirname(key)}/${path.basename(key, path.extname(key))}-parsed`; + await bucket.client.deleteObjectsByPrefix({ prefix: fileParsedPrefix }); }); } if (prefix) { - await prefixDel(bucket, prefix); + addLog.info(`[S3 delete] delete prefix: ${prefix}`); + const tasks = []; + const p = limit(() => retryFn(() => bucket.client.deleteObjectsByPrefix({ prefix }))); + tasks.push(p); + await Promise.all(tasks); + addLog.info(`[S3 delete] delete prefix: ${prefix} success`); } }, { diff --git a/packages/service/common/s3/sources/avatar.ts b/packages/service/common/s3/sources/avatar.ts index 17469b6ab..e4b8b9d1b 100644 --- a/packages/service/common/s3/sources/avatar.ts +++ b/packages/service/common/s3/sources/avatar.ts @@ -25,7 +25,7 @@ class S3AvatarSource extends S3PublicBucket { }) { const { fileKey } = getFileS3Key.avatar({ teamId, filename }); - return this.createPostPresignedUrl( + return this.createPresignedPutUrl( { filename, rawKey: fileKey }, { expiredHours: autoExpired ? 1 : undefined, // 1 Hours diff --git a/packages/service/common/s3/sources/chat/index.ts b/packages/service/common/s3/sources/chat/index.ts index 087c8f3fd..a9d02027f 100644 --- a/packages/service/common/s3/sources/chat/index.ts +++ b/packages/service/common/s3/sources/chat/index.ts @@ -60,21 +60,24 @@ export class S3ChatSource extends S3PrivateBucket { async createUploadChatFileURL(params: CheckChatFileKeys) { const { appId, chatId, uId, filename, expiredTime } = ChatFileUploadSchema.parse(params); const { fileKey } = getFileS3Key.chat({ appId, chatId, uId, filename }); - return await this.createPostPresignedUrl( + return await this.createPresignedPutUrl( { rawKey: fileKey, filename }, { expiredHours: expiredTime ? differenceInHours(expiredTime, new Date()) : 24 } ); } - deleteChatFilesByPrefix(params: DelChatFileByPrefixParams) { + async deleteChatFilesByPrefix(params: DelChatFileByPrefixParams) { const { appId, chatId, uId } = DelChatFileByPrefixSchema.parse(params); const prefix = [S3Sources.chat, appId, uId, chatId].filter(Boolean).join('/'); - return this.addDeleteJob({ prefix }); + await this.addDeleteJob({ prefix }); + global.s3BucketMap[S3Buckets.public]?.addDeleteJob({ prefix }); + return prefix; } deleteChatFileByKey(key: string) { - return this.addDeleteJob({ key }); + this.addDeleteJob({ key }); + return key; } async uploadChatFileByBuffer(params: UploadFileParams) { diff --git a/packages/service/common/s3/sources/dataset/index.ts b/packages/service/common/s3/sources/dataset/index.ts index c9ca9d6aa..82c433f32 100644 --- a/packages/service/common/s3/sources/dataset/index.ts +++ b/packages/service/common/s3/sources/dataset/index.ts @@ -1,6 +1,6 @@ import { S3Sources } from '../../type'; import { S3PrivateBucket } from '../../buckets/private'; -import { parseFileExtensionFromUrl } from '@fastgpt/global/common/string/tools'; +import streamConsumer from 'node:stream/consumers'; import { type CreateGetDatasetFileURLParams, CreateGetDatasetFileURLParamsSchema, @@ -46,7 +46,7 @@ export class S3DatasetSource extends S3PrivateBucket { async createUploadDatasetFileURL(params: CreateUploadDatasetFileParams) { const { filename, datasetId } = CreateUploadDatasetFileParamsSchema.parse(params); const { fileKey } = getFileS3Key.dataset({ datasetId, filename }); - return await this.createPostPresignedUrl({ rawKey: fileKey, filename }, { expiredHours: 3 }); + return await this.createPresignedPutUrl({ rawKey: fileKey, filename }, { expiredHours: 3 }); } // 单个键删除 @@ -71,13 +71,14 @@ export class S3DatasetSource extends S3PrivateBucket { } async getDatasetBase64Image(key: string): Promise { - const [stream, metadata] = await Promise.all([ - this.getFileStream(key), + const [downloadResponse, fileMetadata] = await Promise.all([ + this.client.downloadObject({ key }), this.getFileMetadata(key) ]); - const buffer = await this.fileStreamToBuffer(stream); + + const buffer = await streamConsumer.buffer(downloadResponse.body); const base64 = buffer.toString('base64'); - return `data:${metadata?.contentType || 'image/jpeg'};base64,${base64}`; + return `data:${fileMetadata?.contentType || 'image/jpeg'};base64,${base64}`; } async getDatasetFileRawText(params: GetDatasetFileContentParams) { @@ -95,16 +96,16 @@ export class S3DatasetSource extends S3PrivateBucket { }; } - const [metadata, stream] = await Promise.all([ + const [fileMetadata, downloadResponse] = await Promise.all([ this.getFileMetadata(fileId), - this.getFileStream(fileId) + this.client.downloadObject({ key: fileId }) ]); - const extension = metadata?.extension || ''; - const filename: string = decodeURIComponent(metadata?.filename || ''); + const filename = fileMetadata?.filename || ''; + const extension = fileMetadata?.extension || ''; const start = Date.now(); - const buffer = await this.fileStreamToBuffer(stream); + const buffer = await streamConsumer.buffer(downloadResponse.body); addLog.debug('get dataset file buffer', { time: Date.now() - start }); const encoding = detectFileEncoding(buffer); @@ -144,29 +145,20 @@ export class S3DatasetSource extends S3PrivateBucket { const truncatedFilename = truncateFilename(filename); const { fileKey: key } = getFileS3Key.dataset({ datasetId, filename: truncatedFilename }); - const { stream, size } = (() => { - if ('buffer' in file) { - return { - stream: file.buffer, - size: file.buffer.length - }; - } - return { - stream: file.stream, - size: file.size - }; - })(); - await MongoS3TTL.create({ minioKey: key, bucketName: this.bucketName, expiredTime: addHours(new Date(), 3) }); - await this.putObject(key, stream, size, { - 'content-type': Mimes[path.extname(truncatedFilename) as keyof typeof Mimes], - 'upload-time': new Date().toISOString(), - 'origin-filename': encodeURIComponent(truncatedFilename) + await this.client.uploadObject({ + key, + body: 'buffer' in file ? file.buffer : file.stream, + contentType: Mimes[path.extname(truncatedFilename) as keyof typeof Mimes], + metadata: { + uploadTime: new Date().toISOString(), + originFilename: encodeURIComponent(truncatedFilename) + } }); return key; diff --git a/packages/service/common/s3/sources/rawText/index.ts b/packages/service/common/s3/sources/rawText/index.ts index 5f09e0675..6e2756953 100644 --- a/packages/service/common/s3/sources/rawText/index.ts +++ b/packages/service/common/s3/sources/rawText/index.ts @@ -8,6 +8,7 @@ import { MongoS3TTL } from '../../schema'; import { addMinutes } from 'date-fns'; import { getFileS3Key } from '../../utils'; import { createHash } from 'node:crypto'; +import streamConsumer from 'node:stream/consumers'; export class S3RawTextSource extends S3PrivateBucket { constructor() { @@ -16,10 +17,10 @@ export class S3RawTextSource extends S3PrivateBucket { // 获取文件元数据 async getFilename(key: string) { - const stat = await this.statObject(key); - if (!stat) return ''; + const metadataResponse = await this.client.getObjectMetadata({ key }); + if (!metadataResponse) return ''; - const filename: string = decodeURIComponent(stat.metaData['origin-filename']); + const filename: string = decodeURIComponent(metadataResponse.metadata.originFilename || ''); return filename; } @@ -38,10 +39,14 @@ export class S3RawTextSource extends S3PrivateBucket { expiredTime: addMinutes(new Date(), 20) }); - await this.putObject(key, buffer, buffer.length, { - 'content-type': 'text/plain', - 'origin-filename': encodeURIComponent(sourceName), - 'upload-time': new Date().toISOString() + await this.client.uploadObject({ + key, + body: buffer, + contentType: 'text/plain', + metadata: { + originFilename: encodeURIComponent(sourceName), + uploadTime: new Date().toISOString() + } }); return key; @@ -55,13 +60,16 @@ export class S3RawTextSource extends S3PrivateBucket { if (!(await this.isObjectExists(key))) return null; - const [stream, filename] = await Promise.all([this.getFileStream(key), this.getFilename(key)]); + const [downloadResponse, fileMetadata] = await Promise.all([ + this.client.downloadObject({ key }), + this.getFileMetadata(key) + ]); - const buffer = await this.fileStreamToBuffer(stream); + const buffer = await streamConsumer.buffer(downloadResponse.body); return { text: buffer.toString('utf-8'), - filename + filename: fileMetadata?.filename || '' }; } } diff --git a/packages/service/common/s3/type.ts b/packages/service/common/s3/type.ts index ac638ad77..507b55160 100644 --- a/packages/service/common/s3/type.ts +++ b/packages/service/common/s3/type.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import type { defaultS3Options, Mimes } from './constants'; +import type { Mimes } from './constants'; import type { S3BaseBucket } from './buckets/base'; export const S3MetadataSchema = z.object({ @@ -15,8 +15,6 @@ export type S3Metadata = z.infer; export type ContentType = (typeof Mimes)[keyof typeof Mimes]; export type ExtensionType = keyof typeof Mimes; -export type S3OptionsType = typeof defaultS3Options; - export const S3SourcesSchema = z.enum(['avatar', 'chat', 'dataset', 'temp', 'rawText']); export const S3Sources = S3SourcesSchema.enum; export type S3SourceType = z.infer; diff --git a/packages/service/common/s3/utils.ts b/packages/service/common/s3/utils.ts index 4819199bc..3b24d6fd5 100644 --- a/packages/service/common/s3/utils.ts +++ b/packages/service/common/s3/utils.ts @@ -121,10 +121,14 @@ export async function uploadImage2S3Bucket( const base64Data = base64Img.split(',')[1] || base64Img; const buffer = Buffer.from(base64Data, 'base64'); - await bucket.putObject(uploadKey, buffer, buffer.length, { - 'content-type': mimetype, - 'upload-time': new Date().toISOString(), - 'origin-filename': encodeURIComponent(filename) + await bucket.client.uploadObject({ + key: uploadKey, + body: buffer, + contentType: mimetype, + metadata: { + uploadTime: new Date().toISOString(), + originFilename: encodeURIComponent(filename) + } }); const now = new Date(); @@ -189,16 +193,25 @@ export const getFileS3Key = { appId, chatId, uId, - filename + filename, + isTool = false }: { chatId: string; uId: string; appId: string; - filename: string; + filename?: string; + isTool?: boolean; }) => { const { formatedFilename, extension } = getFormatedFilename(filename); const basePrefix = [S3Sources.chat, appId, uId, chatId].filter(Boolean).join('/'); + if (isTool) { + return { + fileKey: basePrefix, + fileParsedPrefix: '' + }; + } + return { fileKey: [basePrefix, `${formatedFilename}${extension ? `.${extension}` : ''}`].join('/'), fileParsedPrefix: [basePrefix, `${formatedFilename}-parsed`].join('/') diff --git a/packages/service/common/security/fileUrlValidator.ts b/packages/service/common/security/fileUrlValidator.ts index 295c6d288..c10acaa1e 100644 --- a/packages/service/common/security/fileUrlValidator.ts +++ b/packages/service/common/security/fileUrlValidator.ts @@ -1,11 +1,11 @@ const systemWhiteList = (() => { const list: string[] = []; - if (process.env.S3_ENDPOINT) { - list.push(process.env.S3_ENDPOINT); + if (process.env.STORAGE_S3_ENDPOINT) { + list.push(process.env.STORAGE_S3_ENDPOINT); } - if (process.env.S3_EXTERNAL_BASE_URL) { + if (process.env.STORAGE_EXTERNAL_BASE_URL) { try { - const urlData = new URL(process.env.S3_EXTERNAL_BASE_URL); + const urlData = new URL(process.env.STORAGE_EXTERNAL_BASE_URL); list.push(urlData.hostname); } catch (error) {} } diff --git a/packages/service/core/ai/llm/utils.ts b/packages/service/core/ai/llm/utils.ts index 9af77f773..31bc2667a 100644 --- a/packages/service/core/ai/llm/utils.ts +++ b/packages/service/core/ai/llm/utils.ts @@ -171,10 +171,12 @@ export const loadRequestMessages = async ({ const url = await (async () => { if (item.key) { try { - return await getS3ChatSource().createGetChatFileURL({ - key: item.key, - external: false - }); + return ( + await getS3ChatSource().createGetChatFileURL({ + key: item.key, + external: false + }) + ).getUrl; } catch (error) {} } return imgUrl; diff --git a/packages/service/core/chat/utils.ts b/packages/service/core/chat/utils.ts index a68c1faae..d011c44e8 100644 --- a/packages/service/core/chat/utils.ts +++ b/packages/service/core/chat/utils.ts @@ -14,13 +14,15 @@ export const addPreviewUrlToChatItems = async ( async function addToChatflow(item: ChatItemType) { for await (const value of item.value) { if (value.type === ChatItemValueTypeEnum.file && value.file && value.file.key) { - value.file.url = await s3ChatSource.createGetChatFileURL({ + const { getUrl: url } = await s3ChatSource.createGetChatFileURL({ key: value.file.key, external: true }); + value.file.url = url; } } } + async function addToWorkflowTool(item: ChatItemType) { if (item.obj !== ChatRoleEnum.Human || !Array.isArray(item.value)) return; @@ -39,7 +41,7 @@ export const addPreviewUrlToChatItems = async ( for (const file of input.value) { if (!file.key) continue; - const url = await getS3ChatSource().createGetChatFileURL({ + const { getUrl: url } = await getS3ChatSource().createGetChatFileURL({ key: file.key, external: true }); @@ -85,7 +87,7 @@ export const presignVariablesFileUrls = async ({ val.map(async (item) => { if (!item.key) return item; - const url = await getS3ChatSource().createGetChatFileURL({ + const { getUrl: url } = await getS3ChatSource().createGetChatFileURL({ key: item.key, external: true }); diff --git a/packages/service/core/workflow/dispatch/child/runTool.ts b/packages/service/core/workflow/dispatch/child/runTool.ts index ec805a77e..392c266ba 100644 --- a/packages/service/core/workflow/dispatch/child/runTool.ts +++ b/packages/service/core/workflow/dispatch/child/runTool.ts @@ -22,6 +22,7 @@ import { getNodeErrResponse } from '../utils'; import { splitCombineToolId } from '@fastgpt/global/core/app/tool/utils'; import { getAppVersionById } from '../../../../core/app/version/controller'; import { runHTTPTool } from '../../../app/http'; +import { getFileS3Key } from '../../../../common/s3/utils'; type SystemInputConfigType = { type: SystemToolSecretInputTypeEnum; @@ -53,6 +54,12 @@ export const dispatchRunTool = async (props: RunToolProps): Promise = {}; @@ -109,7 +116,8 @@ export const dispatchRunTool = async (props: RunToolProps): Promise { if (item.type !== ChatItemValueTypeEnum.file || !item.file?.key) return; - item.file.url = await getS3ChatSource().createGetChatFileURL({ + const { getUrl: url } = await getS3ChatSource().createGetChatFileURL({ key: item.file.key, external: true }); + item.file.url = url; }), // Remove stopping sign delAgentRuntimeStopSign({ diff --git a/packages/service/core/workflow/dispatch/plugin/runInput.ts b/packages/service/core/workflow/dispatch/plugin/runInput.ts index d5f693742..9835b4407 100644 --- a/packages/service/core/workflow/dispatch/plugin/runInput.ts +++ b/packages/service/core/workflow/dispatch/plugin/runInput.ts @@ -42,11 +42,12 @@ export const dispatchPluginInput = async ( for (let i = 0; i < val.length; i++) { const fileItem = val[i]; if (fileItem.key && !fileItem.url) { - val[i].url = await getS3ChatSource().createGetChatFileURL({ + const { getUrl: url } = await getS3ChatSource().createGetChatFileURL({ key: fileItem.key, external: true, expiredHours: 1 }); + val[i].url = url; } } params[key] = val.map((item) => item.url); diff --git a/packages/service/package.json b/packages/service/package.json index aad8018d2..e7840f40d 100644 --- a/packages/service/package.json +++ b/packages/service/package.json @@ -3,6 +3,7 @@ "version": "1.0.0", "type": "module", "dependencies": { + "@fastgpt-sdk/storage": "workspace:*", "@fastgpt/global": "workspace:*", "@maxmind/geoip2-node": "^6.3.4", "@modelcontextprotocol/sdk": "^1.24.0", @@ -38,6 +39,7 @@ "jsonwebtoken": "^9.0.2", "lodash": "^4.17.21", "mammoth": "^1.11.0", + "mime": "^4.1.0", "minio": "^8.0.5", "mongoose": "^8.10.1", "multer": "2.0.2", @@ -52,6 +54,7 @@ "pg": "^8.10.0", "pino": "^9.7.0", "pino-opentelemetry-transport": "^1.0.1", + "proxy-agent": "^6.5.0", "request-ip": "^3.3.0", "tiktoken": "1.0.17", "tunnel": "^0.0.6", diff --git a/packages/service/support/permission/dataset/auth.ts b/packages/service/support/permission/dataset/auth.ts index b1891c76a..15759414e 100644 --- a/packages/service/support/permission/dataset/auth.ts +++ b/packages/service/support/permission/dataset/auth.ts @@ -202,11 +202,13 @@ export async function authDatasetData({ imageId: datasetData.imageId, imagePreivewUrl: datasetData.imageId && isS3ObjectKey(datasetData.imageId, 'dataset') - ? await getS3DatasetSource().createGetDatasetFileURL({ - key: datasetData.imageId, - expiredHours: 1, - external: true - }) + ? ( + await getS3DatasetSource().createGetDatasetFileURL({ + key: datasetData.imageId, + expiredHours: 1, + external: true + }) + ).getUrl : undefined, chunkIndex: datasetData.chunkIndex, indexes: datasetData.indexes, diff --git a/packages/storage/.node-version b/packages/storage/.node-version new file mode 100644 index 000000000..9de225682 --- /dev/null +++ b/packages/storage/.node-version @@ -0,0 +1 @@ +lts/iron diff --git a/packages/storage/README.md b/packages/storage/README.md new file mode 100644 index 000000000..d5b912d4b --- /dev/null +++ b/packages/storage/README.md @@ -0,0 +1,200 @@ +# @fastgpt-sdk/storage + +FastGPT 的对象存储 SDK,提供 **统一的、与厂商无关的**存储接口(S3/MinIO/OSS/COS 等),用于上传、下载、删除、列举对象以及获取元数据。 + +> 本包为 ESM(`"type": "module"`),并要求 Node.js **>= 20**。 + +## 安装 + +```bash +pnpm add @fastgpt-sdk/storage +``` + +## 快速开始 + +```ts +import { createStorage } from '@fastgpt-sdk/storage'; +import { createWriteStream } from 'node:fs'; + +const storage = createStorage({ + vendor: 'minio', + bucket: 'my-bucket', + region: 'us-east-1', + endpoint: 'http://127.0.0.1:9000', + credentials: { + accessKeyId: process.env.MINIO_ACCESS_KEY ?? '', + secretAccessKey: process.env.MINIO_SECRET_KEY ?? '' + }, + // minio 常见配置:若你的服务不支持 virtual-host 访问方式,可打开它 + forcePathStyle: true +}); + +// 1) 确保 bucket 存在(不存在则尝试创建) +await storage.ensureBucket(); + +// 2) 上传 +await storage.uploadObject({ + key: 'demo/hello.txt', + body: 'hello fastgpt', + contentType: 'text/plain; charset=utf-8', + metadata: { + app: 'fastgpt', + purpose: 'readme-demo' + } +}); + +// 3) 下载(流式) +const { body } = await storage.downloadObject({ key: 'demo/hello.txt' }); +body.pipe(createWriteStream('/tmp/hello.txt')); + +// 4) 删除 +await storage.deleteObject({ key: 'demo/hello.txt' }); + +// 5) 释放资源(部分 adapter 可能是空实现) +await storage.destroy(); +``` + +## 配置(IStorageOptions) + +通过 `vendor` 字段选择适配器(判别联合),不同厂商的配置项在 `IStorageOptions` 上有清晰的类型约束与中文 JSDoc。 + +### AWS S3 + +```ts +import { createStorage } from '@fastgpt-sdk/storage'; + +const storage = createStorage({ + vendor: 'aws-s3', + bucket: 'my-bucket', + region: 'ap-northeast-1', + credentials: { + accessKeyId: process.env.AWS_ACCESS_KEY_ID ?? '', + secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY ?? '' + } +}); +``` + +### MinIO / 其他 S3 兼容 + +```ts +import { createStorage } from '@fastgpt-sdk/storage'; + +const storage = createStorage({ + vendor: 'minio', + bucket: 'my-bucket', + region: 'us-east-1', + endpoint: 'http://127.0.0.1:9000', + credentials: { + accessKeyId: process.env.MINIO_ACCESS_KEY ?? '', + secretAccessKey: process.env.MINIO_SECRET_KEY ?? '' + }, + forcePathStyle: true +}); +``` + +### 阿里云 OSS + +```ts +import { createStorage } from '@fastgpt-sdk/storage'; + +const storage = createStorage({ + vendor: 'oss', + bucket: 'my-bucket', + region: 'oss-cn-hangzhou', + endpoint: process.env.OSS_ENDPOINT, // 视你的部署与 SDK 配置而定 + credentials: { + accessKeyId: process.env.OSS_ACCESS_KEY_ID ?? '', + secretAccessKey: process.env.OSS_ACCESS_KEY_SECRET ?? '' + }, + cname: false, + internal: false +}); +``` + +### 腾讯云 COS + +```ts +import { createStorage } from '@fastgpt-sdk/storage'; + +const storage = createStorage({ + vendor: 'cos', + bucket: 'my-bucket', + region: 'ap-guangzhou', + credentials: { + accessKeyId: process.env.COS_SECRET_ID ?? '', + secretAccessKey: process.env.COS_SECRET_KEY ?? '' + }, + protocol: 'https:', + useAccelerate: false +}); +``` + +## API(IStorage) + +`createStorage(options)` 返回一个实现了 `IStorage` 的实例: + +- **`ensureBucket()`**: 确保 bucket 存在(不存在时**可能**尝试创建,取决于 vendor 与权限;部分厂商仅做存在性校验并直接抛错)。 +- **`checkObjectExists({ key })`**: 判断对象是否存在。 +- **`uploadObject({ key, body, contentType?, contentLength?, contentDisposition?, metadata? })`**: 上传对象。 +- **`downloadObject({ key })`**: 下载对象(返回 `Readable`)。 +- **`deleteObject({ key })`**: 删除单个对象。 +- **`deleteObjectsByMultiKeys({ keys })`**: 按 key 列表批量删除(返回失败 key 列表)。 +- **`deleteObjectsByPrefix({ prefix })`**: 按前缀批量删除(高危,务必使用非空 prefix;返回失败 key 列表)。 +- **`generatePresignedPutUrl({ key, expiredSeconds?, metadata? })`**: 生成 **PUT** 预签名 URL(用于前端直传)。 +- **`generatePresignedGetUrl({ key, expiredSeconds? })`**: 生成 **GET** 预签名 URL(用于临时授权下载)。 +- **`listObjects({ prefix? })`**: 列出对象 key(可按前缀过滤;不传则列出整个 bucket 内对象)。 +- **`getObjectMetadata({ key })`**: 获取对象元数据。 +- **`destroy()`**: 资源清理/连接释放。 + +> 重要:当前实现状态(以代码为准): +> - `generatePresignedPutUrl`:**AWS S3 / MinIO / COS / OSS 已实现**。 +> - `generatePresignedGetUrl`:目前各 adapter 仍为 **未实现**(会抛 `Error('Method not implemented.')`)。 + +### 预签名 PUT 直传示例(浏览器 / 前端) + +`generatePresignedPutUrl` 返回的 `metadata` 字段语义更接近“需要带上的 headers”(不同厂商前缀不同,如 `x-oss-meta-*` / `x-cos-meta-*`)。 + +```ts +const { putUrl, metadata } = await storage.generatePresignedPutUrl({ + key: 'demo/hello.txt', + expiredSeconds: 600, + metadata: { app: 'fastgpt', purpose: 'direct-upload' } +}); + +await fetch(putUrl, { + method: 'PUT', + headers: { + // 将 adapter 返回的 headers 带上(若为空对象也没关系) + ...metadata, + 'content-type': 'text/plain; charset=utf-8' + }, + body: 'hello fastgpt' +}); +``` + +## 错误与异常 + +导出的错误类型: + +- **`NoSuchBucketError`**: bucket 不存在(部分 adapter 会用它包装底层错误)。 +- **`NoBucketReadPermissionError`**: bucket 无读取权限(部分 adapter 会用它包装底层错误)。 +- **`EmptyObjectError`**: 下载时对象为空(例如底层 SDK 返回 `Body` 为空)。 + +建议你在业务层做分层处理:可恢复错误(重试/提示权限)与不可恢复错误(配置错误/接口未实现)。 + +## 注意事项 + +- **按前缀删除是高危操作**:`prefix` 必须是非空字符串;强烈建议使用业务隔离前缀(例如 `team/{teamId}/`),避免误删整桶。 +- **metadata 厂商差异**:不同厂商对元数据 key 前缀/大小写/可用字符/大小限制不同,建议使用简单 ASCII key,并控制总体大小。 +- **流式下载/上传**:大文件建议使用 `Readable`,减少内存峰值。 + +## 开发与构建 + +```bash +pnpm -C FastGPT/packages/storage dev +pnpm -C FastGPT/packages/storage build +``` + +发布前会执行 `prepublishOnly` 自动构建产物到 `dist/`。 + + diff --git a/packages/storage/package.json b/packages/storage/package.json new file mode 100644 index 000000000..a6d0e423d --- /dev/null +++ b/packages/storage/package.json @@ -0,0 +1,62 @@ +{ + "name": "@fastgpt-sdk/storage", + "private": false, + "version": "0.5.1", + "type": "module", + "packageManager": "pnpm@9.15.9", + "description": "FastGPT SDK for object storage", + "author": "FastGPT", + "repository": { + "type": "git", + "url": "https://github.com/labring/FastGPT.git", + "directory": "FastGPT/packages/storage" + }, + "homepage": "https://github.com/labring/FastGPT", + "bugs": { + "url": "https://github.com/labring/FastGPT/issues" + }, + "publishConfig": { + "access": "public" + }, + "engines": { + "node": ">=20" + }, + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } + }, + "files": [ + "dist" + ], + "sideEffects": false, + "license": "MIT", + "keywords": [ + "object-storage", + "storage", + "aws-s3", + "cos", + "minio", + "oss" + ], + "scripts": { + "build": "tsdown", + "dev": "tsdown --watch", + "prepublishOnly": "pnpm build" + }, + "dependencies": { + "@aws-sdk/client-s3": "^3.948.0", + "@aws-sdk/lib-storage": "^3.948.0", + "@aws-sdk/s3-request-presigner": "^3.952.0", + "ali-oss": "^6.23.0", + "cos-nodejs-sdk-v5": "^2.15.4", + "es-toolkit": "^1.43.0" + }, + "devDependencies": { + "@types/ali-oss": "^6.16.13", + "@types/node": "^20", + "tsdown": "^0.17.4", + "typescript": "^5.9.3" + } +} diff --git a/packages/storage/src/adapters/aws-s3.adapter.ts b/packages/storage/src/adapters/aws-s3.adapter.ts new file mode 100644 index 000000000..f8366d9a9 --- /dev/null +++ b/packages/storage/src/adapters/aws-s3.adapter.ts @@ -0,0 +1,426 @@ +import { + CopyObjectCommand, + DeleteObjectCommand, + DeleteObjectsCommand, + GetObjectCommand, + HeadBucketCommand, + HeadObjectCommand, + ListObjectsV2Command, + NotFound, + PutObjectCommand, + S3Client +} from '@aws-sdk/client-s3'; +import type { IAwsS3CompatibleStorageOptions, IStorage } from '../interface'; +import type { + UploadObjectParams, + UploadObjectResult, + DownloadObjectParams, + DownloadObjectResult, + DeleteObjectParams, + DeleteObjectsParams, + DeleteObjectsResult, + PresignedPutUrlParams, + PresignedPutUrlResult, + ListObjectsParams, + ListObjectsResult, + DeleteObjectResult, + GetObjectMetadataParams, + GetObjectMetadataResult, + EnsureBucketResult, + DeleteObjectsByPrefixParams, + StorageObjectKey, + ExistsObjectParams, + ExistsObjectResult, + StorageObjectMetadata, + PresignedGetUrlParams, + PresignedGetUrlResult, + CopyObjectParams, + CopyObjectResult, + GeneratePublicGetUrlParams, + GeneratePublicGetUrlResult +} from '../types'; +import { Upload } from '@aws-sdk/lib-storage'; +import { EmptyObjectError } from '../errors'; +import type { Readable } from 'node:stream'; +import { camelCase, chunk, isNotNil, kebabCase } from 'es-toolkit'; +import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; +import { DEFAULT_PRESIGNED_URL_EXPIRED_SECONDS } from '../constants'; + +export class AwsS3StorageAdapter implements IStorage { + protected readonly client: S3Client; + + get bucketName(): string { + return this.options.bucket; + } + + constructor(protected readonly options: IAwsS3CompatibleStorageOptions) { + if (options.vendor !== 'aws-s3' && options.vendor !== 'minio') { + throw new Error('Invalid storage vendor'); + } + + this.client = new S3Client({ + region: options.region, + credentials: options.credentials, + endpoint: options.endpoint, + forcePathStyle: options.forcePathStyle, + maxAttempts: options.maxRetries + }); + } + + async checkObjectExists(params: ExistsObjectParams): Promise { + const { key } = params; + + let exists = false; + + try { + await this.client.send( + new HeadObjectCommand({ + Bucket: this.options.bucket, + Key: key + }) + ); + exists = true; + } catch (error) { + if (error instanceof NotFound) { + exists = false; + } else { + throw error; + } + } + + return { + key, + exists, + bucket: this.options.bucket + }; + } + + async getObjectMetadata(params: GetObjectMetadataParams): Promise { + const { key } = params; + + const result = await this.client.send( + new HeadObjectCommand({ + Bucket: this.options.bucket, + Key: key + }) + ); + + let metadata: StorageObjectMetadata = {}; + if (result.Metadata) { + for (const [k, v] of Object.entries(result.Metadata)) { + if (!k) continue; + metadata[camelCase(k)] = String(v); + } + } + + return { + key, + metadata, + etag: result.ETag, + bucket: this.options.bucket, + contentType: result.ContentType, + contentLength: result.ContentLength + }; + } + + async ensureBucket(): Promise { + await this.client.send(new HeadBucketCommand({ Bucket: this.options.bucket })); + + return { + exists: true, + created: false, + bucket: this.options.bucket + }; + } + + async uploadObject(params: UploadObjectParams): Promise { + const { key, body, contentType, contentLength, contentDisposition, metadata } = params; + + let meta: StorageObjectMetadata = {}; + if (metadata) { + for (const [k, v] of Object.entries(metadata)) { + if (!k) continue; + meta[kebabCase(k)] = String(v); + } + } + + const upload = new Upload({ + client: this.client, + params: { + Bucket: this.options.bucket, + Key: key, + Body: body, + ContentType: contentType, + ContentLength: contentLength, + ContentDisposition: contentDisposition, + Metadata: meta + } + }); + + await upload.done(); + + return { + key, + bucket: this.options.bucket + }; + } + + async downloadObject(params: DownloadObjectParams): Promise { + const { key } = params; + + const result = await this.client.send( + new GetObjectCommand({ + Bucket: this.options.bucket, + Key: key + }) + ); + + if (!result.Body) { + throw new EmptyObjectError('Object is undefined'); + } + + return { + key, + bucket: this.options.bucket, + body: result.Body as Readable + }; + } + + async deleteObject(params: DeleteObjectParams): Promise { + const { key } = params; + + await this.client.send( + new DeleteObjectCommand({ + Key: key, + Bucket: this.options.bucket + }) + ); + + return { + key, + bucket: this.options.bucket + }; + } + + async deleteObjectsByMultiKeys(params: DeleteObjectsParams): Promise { + const { keys } = params; + + if (keys.length === 0) { + return { + bucket: this.options.bucket, + keys: [] + }; + } + + const chunks = chunk(keys, 1000); + const fails: StorageObjectKey[] = []; + + for (const chunk of chunks) { + const result = await this.client.send( + new DeleteObjectsCommand({ + Bucket: this.options.bucket, + Delete: { + Objects: chunk.map((key) => ({ Key: key })), + Quiet: true + } + }) + ); + fails.push(...(result.Errors?.map((error) => error.Key).filter(isNotNil) ?? [])); + } + + return { + bucket: this.options.bucket, + keys: fails + }; + } + + async deleteObjectsByPrefix(params: DeleteObjectsByPrefixParams): Promise { + const { prefix } = params; + if (!prefix) { + throw new Error('Prefix is required'); + } + + let fails: StorageObjectKey[] = []; + let isTruncated = false; + let continuationToken: string | undefined = undefined; + + do { + const listResponse = await this.client.send( + new ListObjectsV2Command({ + Bucket: this.options.bucket, + Prefix: prefix, + ContinuationToken: continuationToken, + MaxKeys: 1000 + }) + ); + + if (!listResponse.Contents || listResponse.Contents.length === 0) { + return { + bucket: this.options.bucket, + keys: [] + }; + } + + const objectsToDelete = listResponse.Contents.map((content) => ({ Key: content.Key })); + const deleteResponse = await this.client.send( + new DeleteObjectsCommand({ + Bucket: this.options.bucket, + Delete: { + Objects: objectsToDelete, + Quiet: true + } + }) + ); + + fails.push(...(deleteResponse.Errors?.map((error) => error.Key).filter(isNotNil) ?? [])); + + isTruncated = listResponse.IsTruncated ?? false; + continuationToken = listResponse.NextContinuationToken as string | undefined; + } while (isTruncated); + + return { + bucket: this.options.bucket, + keys: fails + }; + } + + async generatePresignedPutUrl(params: PresignedPutUrlParams): Promise { + const { key, expiredSeconds, metadata, contentType } = params; + + const expiresIn = expiredSeconds ? expiredSeconds : DEFAULT_PRESIGNED_URL_EXPIRED_SECONDS; + + // For S3-compatible vendors, metadata is carried by `x-amz-meta-*` headers. + // We return the expected header map so callers can do browser direct-upload with the same metadata. + const meta: Record = {}; + if (metadata) { + for (const [k, v] of Object.entries(metadata)) { + if (!k) continue; + meta[kebabCase(k)] = String(v); + } + } + + if (contentType) { + meta['Content-Type'] = contentType; + } + + const url = await getSignedUrl( + this.client, + new PutObjectCommand({ + Bucket: this.options.bucket, + Key: key, + Metadata: meta + }), + { + expiresIn + } + ); + + return { + key, + putUrl: url, + bucket: this.options.bucket, + metadata: { + 'Content-Type': meta['Content-Type'] + } + }; + } + + async generatePresignedGetUrl(params: PresignedGetUrlParams): Promise { + const { key, expiredSeconds } = params; + + const expiresIn = expiredSeconds ? expiredSeconds : DEFAULT_PRESIGNED_URL_EXPIRED_SECONDS; + + const url = await getSignedUrl( + this.client, + new GetObjectCommand({ + Bucket: this.options.bucket, + Key: key + }), + { + expiresIn + } + ); + + return { + key, + getUrl: url, + bucket: this.options.bucket + }; + } + + generatePublicGetUrl(params: GeneratePublicGetUrlParams): GeneratePublicGetUrlResult { + const { key } = params; + + let url: string; + if (this.options.forcePathStyle) { + url = `${this.options.endpoint}/${this.options.bucket}/${key}`; + } else { + const endpoint = new URL(this.options.endpoint); + url = `${endpoint.protocol}//${this.options.bucket}.${endpoint.host}/${key}`; + } + + return { + key, + publicGetUrl: url, + bucket: this.options.bucket + }; + } + + async listObjects(params: ListObjectsParams): Promise { + const { prefix } = params; + + let keys: StorageObjectKey[] = []; + let isTruncated = false; + let continuationToken: string | undefined = undefined; + + do { + const result = await this.client.send( + new ListObjectsV2Command({ + Bucket: this.options.bucket, + Prefix: prefix, + ContinuationToken: continuationToken, + MaxKeys: 1000 + }) + ); + + if (!result.Contents || result.Contents.length === 0) { + return { + bucket: this.options.bucket, + keys + }; + } + + keys = keys.concat(result.Contents.map((content) => content.Key).filter(isNotNil)); + + isTruncated = result.IsTruncated ?? false; + continuationToken = result.NextContinuationToken as string | undefined; + } while (isTruncated); + + return { + bucket: this.options.bucket, + keys + }; + } + + async copyObjectInSelfBucket(params: CopyObjectParams): Promise { + const { sourceKey, targetKey } = params; + + await this.client.send( + new CopyObjectCommand({ + Bucket: this.options.bucket, + CopySource: `${this.options.bucket}/${sourceKey}`, + Key: targetKey + }) + ); + + return { + bucket: this.options.bucket, + sourceKey, + targetKey + }; + } + + async destroy(): Promise { + this.client.destroy(); + } +} diff --git a/packages/storage/src/adapters/cos.adapter.ts b/packages/storage/src/adapters/cos.adapter.ts new file mode 100644 index 000000000..08936c2ac --- /dev/null +++ b/packages/storage/src/adapters/cos.adapter.ts @@ -0,0 +1,501 @@ +import COS from 'cos-nodejs-sdk-v5'; +import type { ICosStorageOptions, IStorage } from '../interface'; +import type { + UploadObjectParams, + UploadObjectResult, + DownloadObjectParams, + DownloadObjectResult, + DeleteObjectParams, + DeleteObjectsParams, + DeleteObjectsResult, + PresignedPutUrlParams, + PresignedPutUrlResult, + ListObjectsParams, + ListObjectsResult, + DeleteObjectResult, + GetObjectMetadataParams, + GetObjectMetadataResult, + EnsureBucketResult, + DeleteObjectsByPrefixParams, + StorageObjectKey, + ExistsObjectParams, + ExistsObjectResult, + StorageObjectMetadata, + PresignedGetUrlParams, + PresignedGetUrlResult, + CopyObjectParams, + CopyObjectResult, + GeneratePublicGetUrlParams, + GeneratePublicGetUrlResult +} from '../types'; +import { PassThrough } from 'node:stream'; +import { camelCase, isError, isNotNil, kebabCase } from 'es-toolkit'; +import { DEFAULT_PRESIGNED_URL_EXPIRED_SECONDS } from '../constants'; + +export class CosStorageAdapter implements IStorage { + protected readonly client: COS; + + get bucketName(): string { + return this.options.bucket; + } + + constructor(protected readonly options: ICosStorageOptions) { + if (options.vendor !== 'cos') { + throw new Error('Invalid storage vendor'); + } + + this.client = new COS({ + SecretId: options.credentials.accessKeyId, + SecretKey: options.credentials.secretAccessKey, + UseAccelerate: options.useAccelerate, + Protocol: options.protocol, + Domain: options.domain + }); + } + + async checkObjectExists(params: ExistsObjectParams): Promise { + const { key } = params; + + let exists = false; + await new Promise((resolve, reject) => { + this.client.headObject( + { + Bucket: this.options.bucket, + Region: this.options.region, + Key: key + }, + function (err, _data) { + if (err && err.statusCode === 404) { + exists = false; + return resolve(); + } + + if (err) { + return reject(err); + } + + exists = true; + resolve(); + } + ); + }); + + return { + key, + exists, + bucket: this.options.bucket + }; + } + + async getObjectMetadata(params: GetObjectMetadataParams): Promise { + const { key } = params; + + const result = await new Promise((resolve, reject) => { + this.client.headObject( + { + Key: key, + Bucket: this.options.bucket, + Region: this.options.region + }, + function (err, data) { + if (err) { + return reject(err); + } + + resolve(data); + } + ); + }); + + let metadata: StorageObjectMetadata = {}; + if (result.headers) { + Object.entries(result.headers).forEach(([key, val]) => { + if (key.startsWith('x-cos-meta-')) { + metadata[camelCase(key.replace('x-cos-meta-', ''))] = String(val); + } + }); + } + + return { + metadata, + key, + etag: result.ETag, + bucket: this.options.bucket, + contentType: result.headers?.['content-type'], + contentLength: result.headers?.['content-length'] + ? Number(result.headers['content-length']) + : undefined + }; + } + + async ensureBucket(): Promise { + await new Promise((resolve, reject) => { + this.client.headBucket( + { + Bucket: this.options.bucket, + Region: this.options.region + }, + function (err, data) { + if (err) { + return reject(err); + } + + resolve(data); + } + ); + }); + + return { + exists: true, + created: false, + bucket: this.options.bucket + }; + } + + async uploadObject(params: UploadObjectParams): Promise { + const { key, body, contentType, contentLength, contentDisposition, metadata } = params; + + const headers: Record = {}; + if (contentDisposition) headers['Content-Disposition'] = contentDisposition; + + if (metadata) { + for (const [k, v] of Object.entries(metadata)) { + if (!k) continue; + headers[`x-cos-meta-${kebabCase(k)}`] = String(v); + } + } + + await new Promise((resolve, reject) => { + this.client.putObject( + { + Bucket: this.options.bucket, + Region: this.options.region, + Key: key, + Body: body, + ContentType: contentType, + ContentLength: contentLength, + Headers: Object.keys(headers).length ? headers : undefined + }, + function (err, data) { + if (err) { + return reject(err); + } + resolve(data); + } + ); + }); + + return { + key, + bucket: this.options.bucket + }; + } + + async downloadObject(params: DownloadObjectParams): Promise { + const passThrough = new PassThrough(); + + this.client.getObject( + { + Bucket: this.options.bucket, + Region: this.options.region, + Key: params.key, + Output: passThrough + }, + function (err, _data) { + if (err) { + passThrough.destroy(isError(err.error) ? err.error : new Error(err.message)); + } + } + ); + + return { + bucket: this.options.bucket, + key: params.key, + body: passThrough + }; + } + + async deleteObject(params: DeleteObjectParams): Promise { + const { key } = params; + + await new Promise((resolve, reject) => { + this.client.deleteObject( + { + Bucket: this.options.bucket, + Region: this.options.region, + Key: key + }, + function (err, data) { + if (err) { + return reject(err); + } + resolve(data); + } + ); + }); + + return { + key, + bucket: this.options.bucket + }; + } + + async deleteObjectsByMultiKeys(params: DeleteObjectsParams): Promise { + const { keys } = params; + + const result = await new Promise((resolve, reject) => { + this.client.deleteMultipleObject( + { + Bucket: this.options.bucket, + Region: this.options.region, + Objects: keys.map((key) => ({ Key: key })) + }, + function (err, data) { + if (err) { + return reject(err); + } + resolve(data); + } + ); + }); + + return { + keys: result.Error.map((e) => e.Key).filter(isNotNil), + bucket: this.options.bucket + }; + } + + async deleteObjectsByPrefix(params: DeleteObjectsByPrefixParams): Promise { + const { prefix } = params; + if (!prefix) { + throw new Error('Prefix is required'); + } + + const fails: StorageObjectKey[] = []; + let marker: string | undefined = undefined; + + await new Promise((resolve, reject) => { + const handler = () => { + this.client.getBucket( + { + Bucket: this.options.bucket, + Region: this.options.region, + Prefix: prefix, + MaxKeys: 1000, + Marker: marker + }, + (listErr, listData) => { + if (listErr) { + return reject(listErr); + } + + if (!listData.Contents || listData.Contents.length === 0) { + return resolve(); + } + + const objectsToDelete = listData.Contents.map((content) => ({ Key: content.Key })); + + this.client.deleteMultipleObject( + { + Bucket: this.options.bucket, + Region: this.options.region, + Objects: objectsToDelete + }, + function (deleteErr, deleteData) { + if (deleteErr) { + fails.push(...objectsToDelete.map((content) => content.Key)); + if (listData.IsTruncated === 'true') { + marker = listData.NextMarker; + return handler(); + } + + return resolve(); + } + + fails.push(...deleteData.Error.map((e) => e.Key).filter(isNotNil)); + + if (listData.IsTruncated === 'true') { + marker = listData.NextMarker; + return handler(); + } + + resolve(); + } + ); + } + ); + }; + + handler(); + }); + + return { + bucket: this.options.bucket, + keys: fails + }; + } + + async generatePresignedPutUrl(params: PresignedPutUrlParams): Promise { + const { key, expiredSeconds, metadata, contentType } = params; + + const expiresIn = expiredSeconds ? expiredSeconds : DEFAULT_PRESIGNED_URL_EXPIRED_SECONDS; + + const meta: Record = {}; + if (metadata) { + for (const [k, v] of Object.entries(metadata)) { + if (!k) continue; + meta[`x-cos-meta-${kebabCase(k)}`] = String(v); + } + } + + if (contentType) { + meta['Content-Type'] = contentType; + } + + const url = await new Promise((resolve, reject) => { + this.client.getObjectUrl( + { + Bucket: this.options.bucket, + Region: this.options.region, + Key: key, + Expires: expiresIn, + Sign: true, + Method: 'PUT' + }, + function (err, data) { + if (err) { + return reject(err); + } + resolve(data.Url); + } + ); + }); + + return { + key, + putUrl: url, + bucket: this.options.bucket, + metadata: meta + }; + } + + async generatePresignedGetUrl(params: PresignedGetUrlParams): Promise { + const { key, expiredSeconds } = params; + const expiresIn = expiredSeconds ? expiredSeconds : DEFAULT_PRESIGNED_URL_EXPIRED_SECONDS; + + const url = await new Promise((resolve, reject) => { + this.client.getObjectUrl( + { + Bucket: this.options.bucket, + Region: this.options.region, + Key: key, + Expires: expiresIn, + Sign: true, + Method: 'GET' + }, + function (err, data) { + if (err) { + return reject(err); + } + resolve(data.Url); + } + ); + }); + + return { + key, + getUrl: url, + bucket: this.options.bucket + }; + } + + generatePublicGetUrl(params: GeneratePublicGetUrlParams): GeneratePublicGetUrlResult { + const { key } = params; + + let url: string; + if (this.options.domain) { + url = `${this.options.protocol}//${this.options.domain}/${key}`; + } else { + url = `${this.options.protocol}//${this.options.bucket}.cos.${this.options.region}.myqcloud.com/${key}`; + } + + return { + key, + publicGetUrl: url, + bucket: this.options.bucket + }; + } + + async listObjects(params: ListObjectsParams): Promise { + const { prefix } = params; + + let keys: StorageObjectKey[] = []; + let marker: string | undefined = undefined; + + await new Promise((resolve, reject) => { + const handler = () => { + this.client.getBucket( + { + Bucket: this.options.bucket, + Region: this.options.region, + Prefix: prefix, + Marker: marker, + MaxKeys: 1000 + }, + function (err, data) { + if (err) { + return reject(err); + } + + keys = keys.concat(data.Contents?.map((content) => content.Key).filter(isNotNil) ?? []); + + if (data.IsTruncated === 'true') { + marker = data.NextMarker; + return handler(); + } + + resolve(); + } + ); + }; + + handler(); + }); + + return { + keys, + bucket: this.options.bucket + }; + } + + async copyObjectInSelfBucket(params: CopyObjectParams): Promise { + const { sourceKey, targetKey } = params; + + await new Promise((resolve, reject) => { + const copySource = `${this.options.bucket}.cos.${this.options.region}.myqcloud.com/${sourceKey}`; + + this.client.sliceCopyFile( + { + Bucket: this.options.bucket, + Region: this.options.region, + Key: targetKey, + CopySource: copySource + }, + function (err, data) { + if (err) { + return reject(err); + } + resolve(data); + } + ); + }); + + return { + bucket: this.options.bucket, + sourceKey, + targetKey + }; + } + + async destroy(): Promise {} +} diff --git a/packages/storage/src/adapters/minio.adapter.ts b/packages/storage/src/adapters/minio.adapter.ts new file mode 100644 index 000000000..0e4556806 --- /dev/null +++ b/packages/storage/src/adapters/minio.adapter.ts @@ -0,0 +1,60 @@ +import { AwsS3StorageAdapter } from './aws-s3.adapter'; +import type { IAwsS3CompatibleStorageOptions, IStorage } from '../interface'; +import type { EnsureBucketResult } from '../types'; +import { CreateBucketCommand, NotFound, PutBucketPolicyCommand } from '@aws-sdk/client-s3'; + +/** + * 注意: + * - 无论传入的 forcePathStyle 是什么,都强制使用 path style URLs + * - 只有 MinIO 这类 self-hosted 的存储服务会在存储桶不存在时 自动创建两个类型的存储桶 + */ +export class MinioStorageAdapter extends AwsS3StorageAdapter implements IStorage { + constructor(protected readonly options: IAwsS3CompatibleStorageOptions) { + if (options.vendor !== 'minio') { + throw new Error('Invalid storage vendor'); + } + + options.forcePathStyle = true; + + super(options); + } + + async ensureBucket(): Promise { + try { + return await super.ensureBucket(); + } catch (error) { + if (!(error instanceof NotFound)) { + throw error; + } + + await this.client.send(new CreateBucketCommand({ Bucket: this.options.bucket })); + + return { + exists: false, + created: true, + bucket: this.options.bucket + }; + } + } + + async ensurePublicBucketPolicy(): Promise { + const policy = { + Version: '2012-10-17', + Statement: [ + { + Effect: 'Allow', + Principal: '*', + Action: ['s3:GetObject'], + Resource: [`arn:aws:s3:::${this.options.bucket}/*`] + } + ] + }; + + await this.client.send( + new PutBucketPolicyCommand({ + Bucket: this.options.bucket, + Policy: JSON.stringify(policy) + }) + ); + } +} diff --git a/packages/storage/src/adapters/oss.adapter.ts b/packages/storage/src/adapters/oss.adapter.ts new file mode 100644 index 000000000..1193b7301 --- /dev/null +++ b/packages/storage/src/adapters/oss.adapter.ts @@ -0,0 +1,357 @@ +import OSS from 'ali-oss'; +import type { IOssStorageOptions, IStorage } from '../interface'; +import type { + UploadObjectParams, + UploadObjectResult, + DownloadObjectParams, + DownloadObjectResult, + DeleteObjectParams, + DeleteObjectsParams, + DeleteObjectsResult, + PresignedPutUrlParams, + PresignedPutUrlResult, + ListObjectsParams, + ListObjectsResult, + DeleteObjectResult, + GetObjectMetadataParams, + GetObjectMetadataResult, + EnsureBucketResult, + DeleteObjectsByPrefixParams, + StorageObjectKey, + ExistsObjectParams, + ExistsObjectResult, + StorageObjectMetadata, + PresignedGetUrlParams, + PresignedGetUrlResult, + CopyObjectParams, + CopyObjectResult, + GeneratePublicGetUrlParams, + GeneratePublicGetUrlResult +} from '../types'; +import type { Readable } from 'node:stream'; +import { camelCase, difference, kebabCase } from 'es-toolkit'; +import { DEFAULT_PRESIGNED_URL_EXPIRED_SECONDS } from '../constants'; + +export class OosStorageAdapter implements IStorage { + protected readonly client: OSS; + + constructor(protected readonly options: IOssStorageOptions) { + if (options.vendor !== 'oss') { + throw new Error('Invalid storage vendor'); + } + + this.client = new OSS({ + accessKeyId: options.credentials.accessKeyId, + accessKeySecret: options.credentials.secretAccessKey, + region: options.region, + endpoint: options.endpoint, + bucket: options.bucket, + cname: options.cname, + internal: options.internal, + secure: options.secure, + + // @ts-expect-error ali-oss SDK 类型未定义但存在此属性 + enableProxy: options.proxy ? true : false + }); + } + + get bucketName(): string { + return this.options.bucket; + } + + async checkObjectExists(params: ExistsObjectParams): Promise { + const { key } = params; + + let exists = false; + try { + await this.client.head(key); + exists = true; + } catch (error: any) { + if (error?.code === 'NoSuchKey') { + exists = false; + } else { + throw error; + } + } + + return { + key, + exists, + bucket: this.options.bucket + }; + } + + async getObjectMetadata(params: GetObjectMetadataParams): Promise { + const { key } = params; + + const result = await this.client.head(key); + + let metadata: StorageObjectMetadata = {}; + if (result.meta) { + for (const [k, v] of Object.entries(result.meta)) { + if (!k) continue; + metadata[camelCase(k)] = String(v); + } + } + + const headers = result.res.headers as Record; + + return { + key, + metadata, + etag: result.meta?.etag as string, + bucket: this.options.bucket, + contentType: headers['content-type'], + contentLength: headers['content-length'] ? Number(headers['content-length']) : undefined + }; + } + + async ensureBucket(): Promise { + await this.client.getBucketInfo(this.options.bucket); + + return { + exists: true, + created: false, + bucket: this.options.bucket + }; + } + + async uploadObject(params: UploadObjectParams): Promise { + const { key, body, contentType, contentLength, contentDisposition, metadata } = params; + + const headers: Record = { + 'x-oss-storage-class': 'Standard', + 'x-oss-forbid-overwrite': 'false' + }; + if (contentType) headers['Content-Type'] = contentType; + if (contentLength !== undefined) headers['Content-Length'] = String(contentLength); + if (contentDisposition) headers['Content-Disposition'] = contentDisposition; + + let meta = {} as StorageObjectMetadata & OSS.UserMeta; + if (metadata) { + for (const [k, v] of Object.entries(metadata)) { + if (!k) continue; + meta[kebabCase(k)] = String(v); + } + } + + await this.client.put(key, body, { + headers, + mime: contentType, + meta + }); + + return { + key, + bucket: this.options.bucket + }; + } + + async downloadObject(params: DownloadObjectParams): Promise { + const { key } = params; + + const result = await this.client.getStream(key); + + return { + key, + bucket: this.options.bucket, + body: result.stream as Readable + }; + } + + async deleteObject(params: DeleteObjectParams): Promise { + const { key } = params; + + await this.client.delete(key); + + return { + bucket: this.options.bucket, + key + }; + } + + async deleteObjectsByMultiKeys(params: DeleteObjectsParams): Promise { + const { keys } = params; + + const result = await this.client.deleteMulti(keys, { quiet: true }); + + return { + bucket: this.options.bucket, + keys: difference(keys, result.deleted ?? []) + }; + } + + async deleteObjectsByPrefix(params: DeleteObjectsByPrefixParams): Promise { + const { prefix } = params; + if (!prefix) { + throw new Error('Prefix is required'); + } + + const fails: StorageObjectKey[] = []; + let marker: string | undefined = undefined; + let isTruncated = false; + + do { + const listResponse = await this.client.list( + { + prefix, + 'max-keys': 1000, + marker + }, + { + timeout: 60000 + } + ); + + if (!listResponse.objects || listResponse.objects.length === 0) { + return { + bucket: this.options.bucket, + keys: [] + }; + } + + const objectsToDelete = listResponse.objects.map((object) => object.name); + const deleteResponse = await this.deleteObjectsByMultiKeys({ keys: objectsToDelete }); + + fails.push(...deleteResponse.keys); + + isTruncated = listResponse.isTruncated ?? false; + marker = listResponse.nextMarker; + } while (isTruncated); + + return { + bucket: this.options.bucket, + keys: fails + }; + } + + async generatePresignedPutUrl(params: PresignedPutUrlParams): Promise { + const { key, expiredSeconds, metadata, contentType } = params; + + const expiresIn = expiredSeconds ? expiredSeconds : DEFAULT_PRESIGNED_URL_EXPIRED_SECONDS; + + const headersToSign: Record = {}; + if (metadata) { + for (const [k, v] of Object.entries(metadata)) { + if (!k) continue; + headersToSign[`x-oss-meta-${kebabCase(k)}`] = String(v); + } + } + + if (contentType) { + headersToSign['Content-Type'] = contentType; + } + + // @ts-expect-error ali-oss SDK 类型未定义但存在此方法 + // @see https://github.com/ali-sdk/ali-oss?tab=readme-ov-file#signatureurlv4method-expires-request-objectname-additionalheaders + const url = await this.client.signatureUrlV4( + 'PUT', + expiresIn, + { + headers: { + ...headersToSign + } + }, + key + ); + + return { + key, + putUrl: url, + bucket: this.options.bucket, + metadata: headersToSign + }; + } + + async generatePresignedGetUrl(params: PresignedGetUrlParams): Promise { + const { key, expiredSeconds } = params; + const expiresIn = expiredSeconds ? expiredSeconds : DEFAULT_PRESIGNED_URL_EXPIRED_SECONDS; + + const url = this.client.signatureUrl(key, { + method: 'GET', + expires: expiresIn + }); + + return { + key, + getUrl: url, + bucket: this.options.bucket + }; + } + + generatePublicGetUrl(params: GeneratePublicGetUrlParams): GeneratePublicGetUrlResult { + const { key } = params; + + let protocol = 'https:'; + if (!this.options.secure) { + protocol = 'http:'; + } + + let url: string; + if (this.options.cname) { + url = `${protocol}//${this.options.endpoint}/${key}`; + } else { + url = `${protocol}//${this.options.bucket}.${this.options.region}.aliyuncs.com/${key}`; + } + + return { + key, + publicGetUrl: url, + bucket: this.options.bucket + }; + } + + async listObjects(params: ListObjectsParams): Promise { + const { prefix } = params; + + let keys: StorageObjectKey[] = []; + let marker: string | undefined = undefined; + let isTruncated = false; + + do { + const listResponse = await this.client.list( + { + prefix, + 'max-keys': 1000, + marker + }, + { + timeout: 60000 + } + ); + + if (!listResponse.objects || listResponse.objects.length === 0) { + return { + bucket: this.options.bucket, + keys: [] + }; + } + + keys = keys.concat(listResponse.objects.map((object) => object.name)); + isTruncated = listResponse.isTruncated ?? false; + marker = listResponse.nextMarker; + } while (isTruncated); + + return { + keys, + bucket: this.options.bucket + }; + } + + async copyObjectInSelfBucket(params: CopyObjectParams): Promise { + const { sourceKey, targetKey } = params; + + await this.client.copy(sourceKey, targetKey); + + return { + bucket: this.options.bucket, + sourceKey, + targetKey + }; + } + + async destroy(): Promise {} +} + +// Backward compatible export name fix: OSS adapter (typo alias). +export { OosStorageAdapter as OssStorageAdapter }; diff --git a/packages/storage/src/constants.ts b/packages/storage/src/constants.ts new file mode 100644 index 000000000..134983c35 --- /dev/null +++ b/packages/storage/src/constants.ts @@ -0,0 +1,4 @@ +/** + * 默认的预签名 URL 过期时间(秒) + */ +export const DEFAULT_PRESIGNED_URL_EXPIRED_SECONDS = 1800; diff --git a/packages/storage/src/errors.ts b/packages/storage/src/errors.ts new file mode 100644 index 000000000..ab103c52a --- /dev/null +++ b/packages/storage/src/errors.ts @@ -0,0 +1,20 @@ +export class NoSuchBucketError extends Error { + constructor(message: string) { + super(message); + this.name = 'NoSuchBucketError'; + } +} + +export class NoBucketReadPermissionError extends Error { + constructor(message: string) { + super(message); + this.name = 'NoBucketReadPermissionError'; + } +} + +export class EmptyObjectError extends Error { + constructor(message: string) { + super(message); + this.name = 'EmptyObjectError'; + } +} diff --git a/packages/storage/src/factory.ts b/packages/storage/src/factory.ts new file mode 100644 index 000000000..9c733d59a --- /dev/null +++ b/packages/storage/src/factory.ts @@ -0,0 +1,29 @@ +import { AwsS3StorageAdapter } from './adapters/aws-s3.adapter'; +import { CosStorageAdapter } from './adapters/cos.adapter'; +import { MinioStorageAdapter } from './adapters/minio.adapter'; +import { OssStorageAdapter } from './adapters/oss.adapter'; +import type { IStorage, IStorageOptions } from './interface'; + +export function createStorage(options: IStorageOptions): IStorage { + switch (options.vendor) { + case 'aws-s3': { + return new AwsS3StorageAdapter(options); + } + + case 'oss': { + return new OssStorageAdapter(options); + } + + case 'cos': { + return new CosStorageAdapter(options); + } + + case 'minio': { + return new MinioStorageAdapter(options); + } + + default: { + throw new Error(`Unsupported storage vendor: ${String((options as any)?.vendor)}`); + } + } +} diff --git a/packages/storage/src/index.ts b/packages/storage/src/index.ts new file mode 100644 index 000000000..7d0116000 --- /dev/null +++ b/packages/storage/src/index.ts @@ -0,0 +1,40 @@ +export { createStorage } from './factory'; +export type { + IStorage, + IStorageOptions, + IAwsS3CompatibleStorageOptions, + IOssStorageOptions, + ICosStorageOptions, + ICommonStorageOptions +} from './interface'; +export type { + StorageBucketName, + StorageObjectKey, + StorageObjectMetadata, + StorageUploadBody, + EnsureBucketResult, + ExistsObjectParams, + ExistsObjectResult, + UploadObjectParams, + UploadObjectResult, + DownloadObjectParams, + DownloadObjectResult, + DeleteObjectParams, + DeleteObjectResult, + DeleteObjectsParams, + DeleteObjectsResult, + DeleteObjectsByPrefixParams, + PresignedPutUrlParams, + PresignedPutUrlResult, + PresignedGetUrlParams, + PresignedGetUrlResult, + ListObjectsParams, + ListObjectsResult, + GetObjectMetadataParams, + GetObjectMetadataResult +} from './types'; +export { NoSuchBucketError, NoBucketReadPermissionError, EmptyObjectError } from './errors'; +export { AwsS3StorageAdapter } from './adapters/aws-s3.adapter'; +export { CosStorageAdapter } from './adapters/cos.adapter'; +export { MinioStorageAdapter } from './adapters/minio.adapter'; +export { OosStorageAdapter } from './adapters/oss.adapter'; diff --git a/packages/storage/src/interface.ts b/packages/storage/src/interface.ts new file mode 100644 index 000000000..f51a75070 --- /dev/null +++ b/packages/storage/src/interface.ts @@ -0,0 +1,381 @@ +import type { + DeleteObjectParams, + DeleteObjectResult, + DeleteObjectsParams, + DeleteObjectsResult, + DeleteObjectsByPrefixParams, + DownloadObjectParams, + DownloadObjectResult, + EnsureBucketResult, + GetObjectMetadataParams, + GetObjectMetadataResult, + ListObjectsParams, + ListObjectsResult, + PresignedPutUrlParams, + PresignedPutUrlResult, + UploadObjectParams, + UploadObjectResult, + ExistsObjectParams, + ExistsObjectResult, + PresignedGetUrlParams, + PresignedGetUrlResult, + CopyObjectParams, + CopyObjectResult, + GeneratePublicGetUrlParams, + GeneratePublicGetUrlResult +} from './types'; + +/** + * 通用存储配置(与具体云厂商无关)。 + * + * 说明: + * - 本包的适配器以「对象存储」为抽象(S3/OSS/COS/MinIO 等)。 + * - `bucket` / `region` / `credentials` 是大多数厂商的最小必填集合。 + * - `endpoint` 用于 S3 兼容协议的自定义域名/私有部署地址等场景。 + * + * 注意: + * - 不同厂商对 `region` 的含义略有差异(有的会叫作 `region`,有的叫 `location`),这里统一命名为 `region`, + * 由各 adapter 在内部做映射或直传。 + */ +export interface ICommonStorageOptions { + /** + * 存储桶名称(Bucket)。 + * + * - 一般全局唯一(取决于厂商),建议使用小写字母/数字/短横线组合。 + * - 对于已存在的 bucket:此处填写目标 bucket 名称即可。 + */ + bucket: string; + + /** + * 区域(Region / Location)。 + * + * - AWS: 例如 `ap-northeast-1` + * - 腾讯云 COS: 例如 `ap-guangzhou` + * - 阿里云 OSS: 例如 `oss-cn-hangzhou`(具体取值以厂商为准) + */ + region: string; + + /** + * 访问凭证(AK/SK)。 + * + * 注意: + * - 不同厂商字段命名不同,这里统一为 `accessKeyId` / `secretAccessKey`。 + * - 强烈建议从环境变量/密钥管理服务中读取,不要硬编码在仓库里。 + */ + credentials: { + /** AccessKeyId / SecretId / AK */ + accessKeyId: string; + /** SecretAccessKey / SecretKey / SK */ + secretAccessKey: string; + }; +} + +/** + * AWS S3 兼容协议的存储配置。 + * + * 适用范围: + * - AWS S3 + * - MinIO(以及其他兼容 S3 的对象存储) + * + * 设计: + * - 通过 `vendor` 做判别联合(discriminated union),便于在运行时和类型层面区分不同厂商配置。 + */ +export interface IAwsS3CompatibleStorageOptions extends ICommonStorageOptions { + /** + * 存储厂商标识(S3 兼容系)。 + * + * - `aws-s3`: AWS S3 + * - `minio`: MinIO(S3 协议兼容) + */ + vendor: 'aws-s3' | 'minio'; + + /** + * 自定义服务端点(Endpoint),可选。 + * + * 常见用途: + * - MinIO / 私有 S3 兼容服务:`http(s)://host:port` + * - 某些厂商的加速域名、内网域名等 + * + * 注意:是否需要带协议、端口、路径取决于具体 adapter 的实现。 + */ + endpoint: string; + + /** + * 是否强制使用 Path-Style 访问(`/{bucket}/{key}`),可选。 + * + * 背景: + * - S3 支持两种寻址方式:virtual-hosted-style(`{bucket}.endpoint/{key}`)和 path-style(`endpoint/{bucket}/{key}`)。 + * - 一些自建/本地化服务(或特定网络环境)对 virtual-hosted-style 支持不完整,此时可能需要开启。 + */ + forcePathStyle?: boolean; + + /** + * 最大重试次数,可选。 + * + * 说明: + * - 仅影响 adapter 内部使用的 SDK 请求重试策略(如果 adapter 支持)。 + * - 若不设置,通常由 SDK 使用默认值。 + */ + maxRetries?: number; +} + +/** + * 阿里云 OSS 存储配置。 + */ +export interface IOssStorageOptions extends ICommonStorageOptions { + /** 存储厂商标识(OSS)。 */ + vendor: 'oss'; + + /** + * 是否使用自定义域名(CNAME),可选。 + * + * - 开启后通常会影响 endpoint/host 的拼接方式。 + * - 具体行为取决于 OSS SDK 与 adapter 实现。 + */ + cname?: boolean; + + /** + * 自定义服务端点(Endpoint),可选。 + * + * 常见用途: + * - MinIO / 私有 S3 兼容服务:`http(s)://host:port` + * - 某些厂商的加速域名、内网域名等 + * + * 注意:是否需要带协议、端口、路径取决于具体 adapter 的实现。 + */ + endpoint?: string; + + /** + * 是否使用 HTTPS 协议,可选。 + * + * 说明: + * - 默认使用 HTTPS 协议。 + * - 如果设置为 false,则使用 HTTP 协议。 + */ + secure?: boolean; + + /** + * 是否启用代理,可选。 + */ + enableProxy?: boolean; + + /** + * 是否走内网(internal endpoint),可选。 + * + * - 在同地域云内网环境可显著降低延迟与流量费用。 + * - 若设置为 true,adapter 可能会自动选择 internal endpoint。 + */ + internal?: boolean; +} + +/** + * 腾讯云 COS 存储配置。 + */ +export interface ICosStorageOptions extends ICommonStorageOptions { + /** 存储厂商标识(COS)。 */ + vendor: 'cos'; + + /** + * 请求协议,可选。 + * + * - `https:` 为默认推荐 + * - 某些内网/测试环境可能使用 `http:` + */ + protocol?: 'http:' | 'https:'; + + /** + * 是否启用全球加速,可选。 + * + * 说明: + * - 仅当 COS 账号/桶已开通加速能力时才有意义。 + * - 开启后 endpoint/域名可能会发生变化(由 adapter 处理)。 + */ + useAccelerate?: boolean; + + /** + * 自定义域名,可选。 + * + * 说明: + * - 用于替代默认的域名,例如 `https://{bucket}.cos.${region}.myqcloud.com`。 + * - 通常用于某些厂商的私有化部署环境。 + */ + domain?: string; + + /** + * 代理,可选。 + * + * 说明: + * - 用于 HTTP 代理访问,例如 `http://127.0.0.1:8080`。 + */ + proxy?: string; +} + +/** + * 百度 BOS 存储配置(预留)。 + * + * 说明: + * - 当前 `IStorageOptions` 并未包含该类型,可能尚未完整实现/接入。 + * - 先保留接口便于后续扩展。 + */ +export interface IBosStorageOptions extends ICommonStorageOptions { + /** 存储厂商标识(BOS)。 */ + vendor: 'bos'; +} + +/** + * 存储配置联合类型(判别联合)。 + * + * 用法: + * - 根据 `vendor` 字段区分不同厂商配置,adapter 工厂函数通常也会基于该字段选择实现。 + * + * 注意: + * - 当前仅包含 `aws-s3`/`minio`/`oss`/`cos`;若后续接入新厂商,需要在此处补齐联合成员。 + */ +export type IStorageOptions = + | IAwsS3CompatibleStorageOptions + | IOssStorageOptions + | ICosStorageOptions; + +/** + * 统一的对象存储能力接口(vendor-agnostic)。 + * + * 约定: + * - `key` 通常表示对象在 bucket 内的路径(例如 `a/b/c.txt`),由调用方自行约定命名规则。 + * - 所有方法都应当是幂等或尽可能接近幂等(例如删除不存在的对象不应抛出致命错误),以便业务层重试。 + */ +export interface IStorage { + bucketName: string; + + /** + * 确保存储桶存在;若不存在则**可能**尝试创建(取决于 vendor 与账号权限)。 + * + * 返回值说明: + * - `exists`: 调用前 bucket 是否存在 + * - `created`: 本次调用是否创建了 bucket + * + * 建议: + * - 对于 OSS/COS 等厂商,很多团队更倾向于在控制台/基础设施层面创建 bucket(权限/策略/生命周期等更可控), + * 应用侧仅做存在性校验即可(bucket 不存在时会抛出底层 SDK 错误)。 + */ + ensureBucket(): Promise; + + /** + * 判断对象是否存在。 + * + * 返回值说明: + * - `exists`: 对象是否存在 + */ + checkObjectExists(params: ExistsObjectParams): Promise; + + /** + * 上传对象到 bucket。 + * + * 典型用法: + * - 上传文件内容(Buffer/Readable) + * - 上传文本(string) + * + * 注意: + * - `contentType`/`contentDisposition`/`metadata` 会映射为不同厂商的 HTTP 头或元数据字段,adapter 负责兼容。 + */ + uploadObject(params: UploadObjectParams): Promise; + + /** + * 下载对象(以 Node.js `Readable` 流形式返回)。 + * + * 说明: + * - 适合大文件流式读取,避免一次性加载到内存。 + * - 调用方负责消费/关闭流(正常读取结束会自动关闭)。 + */ + downloadObject(params: DownloadObjectParams): Promise; + + /** + * 删除单个对象(按 key)。 + * + * 建议: + * - 作为幂等操作处理:若对象不存在,最好仍返回成功(由 adapter 决定具体行为)。 + */ + deleteObject(params: DeleteObjectParams): Promise; + + /** + * 根据多个 key 批量删除对象。 + * + * 注意: + * - 各厂商对单次批量删除的最大数量限制不同,adapter 可能需要分批处理。 + * - 返回的 `deleted` 通常只包含实际删除/确认删除的 key。 + */ + deleteObjectsByMultiKeys(params: DeleteObjectsParams): Promise; + + /** + * 根据前缀批量删除对象(危险操作)。 + * + * 安全建议: + * - `prefix` 必须是非空字符串,且建议包含业务域前缀(例如 `team/{teamId}/`),避免误删整个 bucket。 + * - 对于大规模删除,adapter 可能会先 list 再 delete,耗时与费用需评估。 + * + * 注意: + * - 理论上可以使用 `this.listObjects` 然后 `this.deleteObjectsByMultiKeys` + * 但是这样可能会产生不必要的内存占用问题,所以这里单独实现了一个方法 + */ + deleteObjectsByPrefix(params: DeleteObjectsByPrefixParams): Promise; + + /** + * 生成对象的上传预签名 URL(Presigned URL)。 + * + * 用途: + * - 前端直传(PUT) + * + * 注意: + * - 过期时间、签名算法、header 约束等通常由 adapter 或其底层 SDK 决定。 + * - 返回值中的 `metadata` 字段语义更接近“直传时需要附带的 headers”(不同厂商前缀不同,如 `x-oss-meta-*` / `x-cos-meta-*`)。 + * 字段名因历史原因沿用 `metadata`。 + */ + generatePresignedPutUrl(params: PresignedPutUrlParams): Promise; + + /** + * 生成对象的下载预签名 URL(Presigned URL)。 + * + * 用途: + * - 临时授权下载(GET) + */ + generatePresignedGetUrl(params: PresignedGetUrlParams): Promise; + + /** + * 生成公共对象的访问 URL。 + */ + generatePublicGetUrl(params: GeneratePublicGetUrlParams): GeneratePublicGetUrlResult; + + /** + * 列出对象 key(可按前缀过滤)。 + * + * 注意: + * - 当前返回结构只包含 key 列表,未包含分页/marker/continuationToken 等信息; + * 若业务需要大规模遍历,应扩展 `ListObjectsParams/Result` 支持分页与更多元数据。 + * - `prefix` 为可选;不传则表示列出整个 bucket 内对象(注意对象很多时可能会很慢/很贵)。 + * - 不要用 listObjects + deleteObjectsByMultiKeys 来实现“按前缀删除”:批量删除单次最多 1000 个对象,且 list 结果量可能很大; + * 请使用 `deleteObjectsByPrefix`(adapter 会在内部分页与分批删除)。 + */ + listObjects(params: ListObjectsParams): Promise; + + /** + * 复制对象。 + */ + copyObjectInSelfBucket(params: CopyObjectParams): Promise; + + /** + * 获取对象元数据(Metadata)。 + * + * 说明: + * - 元数据通常包含用户自定义 metadata 以及部分系统字段(取决于 adapter 的实现)。 + * - 不同厂商会对 metadata 的 key 前缀、大小写、可用字符做限制,调用方应尽量使用简单的 ASCII key。 + */ + getObjectMetadata(params: GetObjectMetadataParams): Promise; + + /** + * 资源清理/连接释放。 + * + * 说明: + * - 某些 SDK 会维护连接池或后台任务,业务在进程退出前可调用以更快释放资源。 + * - 若 adapter 无需清理,应实现为空操作(resolved Promise)。 + */ + destroy(): Promise; +} diff --git a/packages/storage/src/types.ts b/packages/storage/src/types.ts new file mode 100644 index 000000000..543b29924 --- /dev/null +++ b/packages/storage/src/types.ts @@ -0,0 +1,388 @@ +import type { Readable } from 'node:stream'; + +/** + * 对象存储(S3/MinIO/OSS/COS/...)统一类型定义。 + * + * 设计目标: + * - **与厂商无关**:业务侧只依赖这些类型,不直接依赖具体云 SDK 的类型。 + * - **Node 友好**:避免 DOM 专属类型(例如 `Blob` / `ReadableStream`),在服务端环境开箱即用。 + * - **可扩展**:当新增厂商或能力(分页、分片上传、ACL 等)时,优先在这里扩展类型,再由各 adapter 负责实现。 + */ + +/** + * 存储桶名称(Bucket name)。 + * + * 说明: + * - 本质上是 string,但为了语义清晰单独起别名。 + * - 具体命名规则由厂商决定(长度、字符集、是否全局唯一等)。 + */ +export type StorageBucketName = string; + +/** + * 对象 key(Object key / object path)。 + * + * 说明: + * - 在同一个 bucket 内唯一标识一个对象。 + * - 通常形如:`a/b/c.txt`(用 `/` 形成“目录”层级,但对象存储并不是真正的目录结构)。 + */ +export type StorageObjectKey = string; + +/** + * 对象元数据(Metadata)。 + * + * 说明: + * - 用于承载用户自定义键值对(以及 adapter 可能返回的部分系统字段)。 + * - 由于不同厂商对 key/value 的限制差异较大,这里使用宽泛的 `Record`,由 adapter 做必要的转换/过滤。 + * + * 建议: + * - 自定义 key 尽量使用小写 ASCII 与短横线/下划线,避免特殊字符与大小写歧义。 + */ +export type StorageObjectMetadata = Record; + +/** + * 上传内容(body)支持的类型(Node.js 环境)。 + * + * - `Buffer`: 二进制内容(推荐用于小/中等体积文件)。 + * - `string`: 文本内容(注意编码,一般为 UTF-8)。 + * - `Readable`: 流式上传(推荐用于大文件,避免内存峰值)。 + * + * 说明: + * - 这里刻意不引入浏览器侧类型(如 `Blob`),让该包在服务端 tsconfig 下更稳定。 + */ +export type StorageUploadBody = Buffer | string | Readable; + +/** + * `ensureBucket` 的返回结果。 + */ +export type EnsureBucketResult = { + /** 调用前 bucket 是否已经存在。 */ + exists: boolean; + /** 本次调用是否创建了 bucket(存在则为 false)。 */ + created: boolean; + /** bucket 名称(回显)。 */ + bucket: StorageBucketName; +}; + +/** + * 上传对象入参。 + */ +export type UploadObjectParams = { + /** 对象 key。 */ + key: StorageObjectKey; + /** 上传内容。 */ + body: StorageUploadBody; + + /** + * MIME 类型(Content-Type),可选。 + * + * 示例:`image/png`、`application/pdf`、`text/plain; charset=utf-8` + */ + contentType?: string; + + /** + * 内容长度(字节),可选。 + * + * 说明: + * - 某些 SDK/厂商在特定上传方式下需要该值;不填时可能由 SDK 自动计算或走 chunked 传输。 + */ + contentLength?: number; + + /** + * 内容展示方式(Content-Disposition),可选。 + * + * 示例: + * - `inline` + * - `attachment; filename="report.pdf"` + */ + contentDisposition?: string; + + /** + * 自定义元数据(key/value),可选。 + * + * 注意: + * - 不同厂商会使用不同的 header 前缀/命名规则(例如 `x-amz-meta-` 等),adapter 会负责映射。 + * - 元数据大小、字符集限制由厂商决定;尽量保持 key 简洁并控制总体大小。 + */ + metadata?: StorageObjectMetadata; +}; + +/** + * 上传对象返回结果(最小回执)。 + * + * 说明: + * - 目前仅回传 `bucket` 与 `key`,不包含 ETag/版本号/校验和等信息; + * 若业务侧需要这些字段,可以在后续迭代中扩展。 + */ +export type UploadObjectResult = { + /** bucket 名称。 */ + bucket: StorageBucketName; + /** 对象 key。 */ + key: StorageObjectKey; +}; + +/** + * 下载对象入参。 + */ +export type DownloadObjectParams = { + /** 对象 key。 */ + key: StorageObjectKey; +}; + +/** + * 下载对象结果(流式)。 + */ +export type DownloadObjectResult = { + /** bucket 名称。 */ + bucket: StorageBucketName; + /** 对象 key。 */ + key: StorageObjectKey; + + /** + * 对象内容(Node.js 可读流)。 + * + * 使用建议: + * - 直接 pipe 到文件或 HTTP 响应,避免一次性读入内存: + * `body.pipe(fs.createWriteStream(...))` + */ + body: Readable; +}; + +/** + * 删除单个对象入参。 + */ +export type DeleteObjectParams = { + /** 对象 key。 */ + key: StorageObjectKey; +}; + +/** + * 删除单个对象结果(最小回执)。 + */ +export type DeleteObjectResult = { + /** bucket 名称。 */ + bucket: StorageBucketName; + /** 对象 key。 */ + key: StorageObjectKey; +}; + +/** + * 批量删除对象入参(按 key 列表)。 + */ +export type DeleteObjectsParams = { + /** 要删除的对象 key 列表。 */ + keys: StorageObjectKey[]; +}; + +/** + * 批量删除对象结果。 + */ +export type DeleteObjectsResult = { + /** bucket 名称。 */ + bucket: StorageBucketName; + /** 删除失败的对象 key 列表。 */ + keys: StorageObjectKey[]; +}; + +/** + * 生成上传预签名 URL 入参。 + */ +export type PresignedPutUrlParams = { + /** 对象 key。 */ + key: StorageObjectKey; + /** 过期时间(秒),可选,默认 1800 秒。 */ + expiredSeconds?: number; + + /** + * MIME 类型(Content-Type),可选。 + * + * 示例:`image/png`、`application/pdf`、`text/plain; charset=utf-8` + */ + contentType?: string; + + /** + * 自定义元数据(key/value),可选。 + * + * 注意: + * - 不同厂商会使用不同的 header 前缀/命名规则(例如 `x-amz-meta-` 等),adapter 会负责映射。 + * - 元数据大小、字符集限制由厂商决定;尽量保持 key 简洁并控制总体大小。 + */ + metadata?: StorageObjectMetadata; +}; + +/** + * 生成上传预签名 URL 结果。 + */ +export type PresignedPutUrlResult = { + /** bucket 名称。 */ + bucket: StorageBucketName; + /** 对象 key。 */ + key: StorageObjectKey; + /** 可直接访问的临时 URL。 */ + putUrl: string; + /** + * 与本次 PUT 直传相关的“需要带上的 header”集合。 + * + * 说明: + * - 不同厂商对自定义元数据的 header 前缀不同(例如 S3 是 `x-amz-meta-*`,COS 是 `x-cos-meta-*`,OSS 是 `x-oss-meta-*`)。 + * - 为了让调用方在前端直传时更容易使用,这里统一通过该字段返回 adapter 期望的 header key/value。 + * + * 注意: + * - 该字段名历史原因沿用 `metadata`,但语义更接近“headers”而非纯业务元数据。 + */ + metadata: Record; +}; + +/** + * 生成下载预签名 URL 入参。 + */ +export type PresignedGetUrlParams = { + /** 对象 key。 */ + key: StorageObjectKey; + /** 过期时间(秒),可选,默认 1800 秒。 */ + expiredSeconds?: number; +}; + +/** + * 生成下载预签名 URL 结果。 + */ +export type PresignedGetUrlResult = { + /** bucket 名称。 */ + bucket: StorageBucketName; + /** 对象 key。 */ + key: StorageObjectKey; + /** 可直接访问的临时 URL。 */ + getUrl: string; +}; + +/** + * 生成公共对象的访问 URL 入参。 + */ +export type GeneratePublicGetUrlParams = { + /** 对象 key。 */ + key: StorageObjectKey; +}; + +/** + * 生成公共对象的访问 URL 结果。 + */ +export type GeneratePublicGetUrlResult = { + /** 可直接访问的公共 URL。 */ + publicGetUrl: string; + /** bucket 名称。 */ + bucket: StorageBucketName; + /** 对象 key。 */ + key: StorageObjectKey; +}; + +/** + * 列表查询入参(按前缀过滤)。 + * + * 注意: + * - 当前类型未包含分页参数;当对象数量很多时,adapter 可能需要自行分页并在内部合并结果(或未来扩展此类型)。 + */ +export type ListObjectsParams = { + /** + * 前缀过滤(prefix),可选。 + * + * 示例:`team/123/` 会列出该前缀下的所有对象 key。 + */ + prefix?: string; +}; + +/** + * 列表查询结果(仅返回 key 列表)。 + */ +export type ListObjectsResult = { + /** bucket 名称。 */ + bucket: StorageBucketName; + /** 对象 key 列表。 */ + keys: StorageObjectKey[]; +}; + +/** + * 复制对象入参。 + */ +export type CopyObjectParams = { + /** 源对象 key。 */ + sourceKey: StorageObjectKey; + /** 目标对象 key。 */ + targetKey: StorageObjectKey; +}; + +/** + * 复制对象结果。 + */ +export type CopyObjectResult = { + /** bucket 名称。 */ + bucket: StorageBucketName; + /** 源对象 key。 */ + sourceKey: StorageObjectKey; + /** 目标对象 key。 */ + targetKey: StorageObjectKey; +}; + +/** + * 获取对象元数据入参。 + */ +export type GetObjectMetadataParams = { + /** 对象 key。 */ + key: StorageObjectKey; +}; + +/** + * 获取对象元数据结果。 + */ +export type GetObjectMetadataResult = { + /** bucket 名称。 */ + bucket: StorageBucketName; + /** 对象 key。 */ + key: StorageObjectKey; + /** 元数据。 */ + metadata: StorageObjectMetadata; + /** MIME 类型(Content-Type)。 */ + contentType?: string; + /** 内容长度(字节)。 */ + contentLength?: number; + /** ETag。 */ + etag?: string; +}; + +/** + * 按前缀批量删除入参(高危)。 + * + * 说明: + * - 通常实现方式是:先按 prefix 列出对象,再分批删除。 + * - 这可能会产生较多 API 调用与费用,并且在对象数很大时耗时较长。 + */ +export type DeleteObjectsByPrefixParams = { + /** + * 前缀(prefix),必须为**非空字符串**。 + * + * 安全原因: + * - 若允许空字符串,等价于删除整个 bucket 内所有对象,风险极高。 + * + * 建议: + * - 使用强业务隔离前缀,例如:`team/{teamId}/`、`dataset/{datasetId}/`。 + */ + prefix: string; +}; + +/** + * 判断对象是否存在入参。 + */ +export type ExistsObjectParams = { + /** 对象 key。 */ + key: StorageObjectKey; +}; + +/** + * 判断对象是否存在结果。 + */ +export type ExistsObjectResult = { + /** bucket 名称。 */ + bucket: StorageBucketName; + /** 对象 key。 */ + key: StorageObjectKey; + /** 对象是否存在。 */ + exists: boolean; +}; diff --git a/packages/storage/tsconfig.json b/packages/storage/tsconfig.json new file mode 100644 index 000000000..079d7741a --- /dev/null +++ b/packages/storage/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "esnext", + "module": "esnext", + "moduleResolution": "bundler", + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "resolveJsonModule": true, + "isolatedModules": true, + } +} diff --git a/packages/storage/tsdown.config.ts b/packages/storage/tsdown.config.ts new file mode 100644 index 000000000..6273d1901 --- /dev/null +++ b/packages/storage/tsdown.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from 'tsdown'; + +export default defineConfig({ + entry: 'src/index.ts', + format: 'esm', + dts: { + enabled: true, + sourcemap: false + }, + outExtensions() { + return { + dts: '.d.ts', + js: '.js' + }; + } +}); diff --git a/packages/web/common/file/hooks/useUploadAvatar.tsx b/packages/web/common/file/hooks/useUploadAvatar.tsx index b6df4c008..38c1958b9 100644 --- a/packages/web/common/file/hooks/useUploadAvatar.tsx +++ b/packages/web/common/file/hooks/useUploadAvatar.tsx @@ -37,13 +37,19 @@ export const useUploadAvatar = ( }), file.name ); - const { url, fields } = await api({ filename: file.name }); - const formData = new FormData(); - Object.entries(fields).forEach(([k, v]) => formData.set(k, v)); - formData.set('file', compressed); - const res = await fetch(url, { method: 'POST', body: formData }); // 204 - if (res.ok && res.status === 204) { - onSuccess?.(`${imageBaseUrl}${fields.key}`); + const { + url, + fields: { key, ...headers } + } = await api({ filename: file.name }); + const res = await fetch(url, { + method: 'PUT', + body: compressed, + headers: { + ...headers + } + }); + if (res.ok && res.status === 200) { + onSuccess?.(`${imageBaseUrl}${key}`); } }); }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5e47c035b..6c5a91d90 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -72,8 +72,8 @@ importers: specifier: ^1.2.8 version: 1.2.8 '@fastgpt-sdk/plugin': - specifier: 0.2.16 - version: 0.2.16(@types/node@20.14.0) + specifier: 0.2.17 + version: 0.2.17(@types/node@20.14.0) axios: specifier: ^1.12.1 version: 1.12.1 @@ -132,6 +132,9 @@ importers: packages/service: dependencies: + '@fastgpt-sdk/storage': + specifier: workspace:* + version: link:../storage '@fastgpt/global': specifier: workspace:* version: link:../global @@ -237,6 +240,9 @@ importers: mammoth: specifier: ^1.11.0 version: 1.11.0 + mime: + specifier: ^4.1.0 + version: 4.1.0 minio: specifier: ^8.0.5 version: 8.0.5 @@ -279,6 +285,9 @@ importers: pino-opentelemetry-transport: specifier: ^1.0.1 version: 1.0.1(@opentelemetry/api@1.9.0)(pino@9.7.0) + proxy-agent: + specifier: ^6.5.0 + version: 6.5.0 request-ip: specifier: ^3.3.0 version: 3.3.0 @@ -335,6 +344,40 @@ importers: specifier: ^5.0.4 version: 5.0.5 + packages/storage: + dependencies: + '@aws-sdk/client-s3': + specifier: ^3.948.0 + version: 3.948.0 + '@aws-sdk/lib-storage': + specifier: ^3.948.0 + version: 3.948.0(@aws-sdk/client-s3@3.948.0) + '@aws-sdk/s3-request-presigner': + specifier: ^3.952.0 + version: 3.952.0 + ali-oss: + specifier: ^6.23.0 + version: 6.23.0 + cos-nodejs-sdk-v5: + specifier: ^2.15.4 + version: 2.15.4 + es-toolkit: + specifier: ^1.43.0 + version: 1.43.0 + devDependencies: + '@types/ali-oss': + specifier: ^6.16.13 + version: 6.16.13 + '@types/node': + specifier: ^20 + version: 20.17.24 + tsdown: + specifier: ^0.17.4 + version: 0.17.4(typescript@5.9.3) + typescript: + specifier: ^5.9.3 + version: 5.9.3 + packages/web: dependencies: '@chakra-ui/anatomy': @@ -981,6 +1024,179 @@ packages: peerDependencies: openapi-types: '>=7' + '@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.948.0': + resolution: {integrity: sha512-uvEjds8aYA9SzhBS8RKDtsDUhNV9VhqKiHTcmvhM7gJO92q0WTn8/QeFTdNyLc6RxpiDyz+uBxS7PcdNiZzqfA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/client-sso@3.948.0': + resolution: {integrity: sha512-iWjchXy8bIAVBUsKnbfKYXRwhLgRg3EqCQ5FTr3JbR+QR75rZm4ZOYXlvHGztVTmtAZ+PQVA1Y4zO7v7N87C0A==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/core@3.947.0': + resolution: {integrity: sha512-Khq4zHhuAkvCFuFbgcy3GrZTzfSX7ZIjIcW1zRDxXRLZKRtuhnZdonqTUfaWi5K42/4OmxkYNpsO7X7trQOeHw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-env@3.947.0': + resolution: {integrity: sha512-VR2V6dRELmzwAsCpK4GqxUi6UW5WNhAXS9F9AzWi5jvijwJo3nH92YNJUP4quMpgFZxJHEWyXLWgPjh9u0zYOA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-http@3.947.0': + resolution: {integrity: sha512-inF09lh9SlHj63Vmr5d+LmwPXZc2IbK8lAruhOr3KLsZAIHEgHgGPXWDC2ukTEMzg0pkexQ6FOhXXad6klK4RA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-ini@3.948.0': + resolution: {integrity: sha512-Cl//Qh88e8HBL7yYkJNpF5eq76IO6rq8GsatKcfVBm7RFVxCqYEPSSBtkHdbtNwQdRQqAMXc6E/lEB/CZUDxnA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-login@3.948.0': + resolution: {integrity: sha512-gcKO2b6eeTuZGp3Vvgr/9OxajMrD3W+FZ2FCyJox363ZgMoYJsyNid1vuZrEuAGkx0jvveLXfwiVS0UXyPkgtw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-node@3.948.0': + resolution: {integrity: sha512-ep5vRLnrRdcsP17Ef31sNN4g8Nqk/4JBydcUJuFRbGuyQtrZZrVT81UeH2xhz6d0BK6ejafDB9+ZpBjXuWT5/Q==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-process@3.947.0': + resolution: {integrity: sha512-WpanFbHe08SP1hAJNeDdBDVz9SGgMu/gc0XJ9u3uNpW99nKZjDpvPRAdW7WLA4K6essMjxWkguIGNOpij6Do2Q==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-sso@3.948.0': + resolution: {integrity: sha512-gqLhX1L+zb/ZDnnYbILQqJ46j735StfWV5PbDjxRzBKS7GzsiYoaf6MyHseEopmWrez5zl5l6aWzig7UpzSeQQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.948.0': + resolution: {integrity: sha512-MvYQlXVoJyfF3/SmnNzOVEtANRAiJIObEUYYyjTqKZTmcRIVVky0tPuG26XnB8LmTYgtESwJIZJj/Eyyc9WURQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/lib-storage@3.948.0': + resolution: {integrity: sha512-dY7wISfWgEqSHGps0DkQiDjHhCqR7bc0mMrBHZ810/j12uzhTakAcb9FlF7mFWkX6zEvz2kjxF4r91lBwNqt5w==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@aws-sdk/client-s3': ^3.948.0 + + '@aws-sdk/middleware-bucket-endpoint@3.936.0': + resolution: {integrity: sha512-XLSVVfAorUxZh6dzF+HTOp4R1B5EQcdpGcPliWr0KUj2jukgjZEcqbBmjyMF/p9bmyQsONX80iURF1HLAlW0qg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-expect-continue@3.936.0': + resolution: {integrity: sha512-Eb4ELAC23bEQLJmUMYnPWcjD3FZIsmz2svDiXEcxRkQU9r7NRID7pM7C5NPH94wOfiCk0b2Y8rVyFXW0lGQwbA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-flexible-checksums@3.947.0': + resolution: {integrity: sha512-kXXxS2raNESNO+zR0L4YInVjhcGGNI2Mx0AE1ThRhDkAt2se3a+rGf9equ9YvOqA1m8Jl/GSI8cXYvSxXmS9Ag==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-host-header@3.936.0': + resolution: {integrity: sha512-tAaObaAnsP1XnLGndfkGWFuzrJYuk9W0b/nLvol66t8FZExIAf/WdkT2NNAWOYxljVs++oHnyHBCxIlaHrzSiw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-location-constraint@3.936.0': + resolution: {integrity: sha512-SCMPenDtQMd9o5da9JzkHz838w3327iqXk3cbNnXWqnNRx6unyW8FL0DZ84gIY12kAyVHz5WEqlWuekc15ehfw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-logger@3.936.0': + resolution: {integrity: sha512-aPSJ12d3a3Ea5nyEnLbijCaaYJT2QjQ9iW+zGh5QcZYXmOGWbKVyPSxmVOboZQG+c1M8t6d2O7tqrwzIq8L8qw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-recursion-detection@3.948.0': + resolution: {integrity: sha512-Qa8Zj+EAqA0VlAVvxpRnpBpIWJI9KUwaioY1vkeNVwXPlNaz9y9zCKVM9iU9OZ5HXpoUg6TnhATAHXHAE8+QsQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-sdk-s3@3.947.0': + resolution: {integrity: sha512-DS2tm5YBKhPW2PthrRBDr6eufChbwXe0NjtTZcYDfUCXf0OR+W6cIqyKguwHMJ+IyYdey30AfVw9/Lb5KB8U8A==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-ssec@3.936.0': + resolution: {integrity: sha512-/GLC9lZdVp05ozRik5KsuODR/N7j+W+2TbfdFL3iS+7un+gnP6hC8RDOZd6WhpZp7drXQ9guKiTAxkZQwzS8DA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-user-agent@3.947.0': + resolution: {integrity: sha512-7rpKV8YNgCP2R4F9RjWZFcD2R+SO/0R4VHIbY9iZJdH2MzzJ8ZG7h8dZ2m8QkQd1fjx4wrFJGGPJUTYXPV3baA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/nested-clients@3.948.0': + resolution: {integrity: sha512-zcbJfBsB6h254o3NuoEkf0+UY1GpE9ioiQdENWv7odo69s8iaGBEQ4BDpsIMqcuiiUXw1uKIVNxCB1gUGYz8lw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/region-config-resolver@3.936.0': + resolution: {integrity: sha512-wOKhzzWsshXGduxO4pqSiNyL9oUtk4BEvjWm9aaq6Hmfdoydq6v6t0rAGHWPjFwy9z2haovGRi3C8IxdMB4muw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/s3-request-presigner@3.952.0': + resolution: {integrity: sha512-K/rJxP3O6TKTzDsBoVpExCZZlKbfY3SWNaR7ilm+mwBS/EXqY7sObYZU4Yhl+8aQlRTqDHgOOkR2+Qws0qD54Q==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/signature-v4-multi-region@3.947.0': + resolution: {integrity: sha512-UaYmzoxf9q3mabIA2hc4T6x5YSFUG2BpNjAZ207EA1bnQMiK+d6vZvb83t7dIWL/U1de1sGV19c1C81Jf14rrA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/token-providers@3.948.0': + resolution: {integrity: sha512-V487/kM4Teq5dcr1t5K6eoUKuqlGr9FRWL3MIMukMERJXHZvio6kox60FZ/YtciRHRI75u14YUqm2Dzddcu3+A==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/types@3.936.0': + resolution: {integrity: sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-arn-parser@3.893.0': + resolution: {integrity: sha512-u8H4f2Zsi19DGnwj5FSZzDMhytYF/bCh37vAtBsn3cNDL3YG578X5oc+wSX54pM3tOxS+NY7tvOAo52SW7koUA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-endpoints@3.936.0': + resolution: {integrity: sha512-0Zx3Ntdpu+z9Wlm7JKUBOzS9EunwKAb4KdGUQQxDqh5Lc3ta5uBoub+FgmVuzwnmBu9U1Os8UuwVTH0Lgu+P5w==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-format-url@3.936.0': + resolution: {integrity: sha512-MS5eSEtDUFIAMHrJaMERiHAvDPdfxc/T869ZjDNFAIiZhyc037REw0aoTNeimNXDNy2txRNZJaAUn/kE4RwN+g==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-locate-window@3.893.0': + resolution: {integrity: sha512-T89pFfgat6c8nMmpI8eKjBcDcgJq36+m9oiXbcUzeU55MP9ZuGgBomGjGnHaEyF36jenW9gmg3NfZDm0AO2XPg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-user-agent-browser@3.936.0': + resolution: {integrity: sha512-eZ/XF6NxMtu+iCma58GRNRxSq4lHo6zHQLOZRIeL/ghqYJirqHdenMOwrzPettj60KWlv827RVebP9oNVrwZbw==} + + '@aws-sdk/util-user-agent-node@3.947.0': + resolution: {integrity: sha512-+vhHoDrdbb+zerV4noQk1DHaUMNzWFWPpPYjVTwW2186k5BEJIecAMChYkghRrBVJ3KPWP1+JnZwOd72F3d4rQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + aws-crt: '>=1.0.0' + peerDependenciesMeta: + aws-crt: + optional: true + + '@aws-sdk/xml-builder@3.930.0': + resolution: {integrity: sha512-YIfkD17GocxdmlUVc3ia52QhcWuRIUJonbF8A2CYfcWNV3HzvAqpcPeC0bYUhkK+8e8YO1ARnLKZQE0TlwzorA==} + engines: {node: '>=18.0.0'} + + '@aws/lambda-invoke-store@0.2.2': + resolution: {integrity: sha512-C0NBLsIqzDIae8HFw9YIrIBsbc0xTiOtt7fAukGPnqQ/+zZNaq+4jhuccltK0QuWHBnNm/a6kLIRA6GFiM10eg==} + engines: {node: '>=18.0.0'} + '@babel/code-frame@7.26.2': resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} @@ -997,6 +1213,10 @@ packages: resolution: {integrity: sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==} engines: {node: '>=6.9.0'} + '@babel/generator@7.28.5': + resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} + engines: {node: '>=6.9.0'} + '@babel/helper-annotate-as-pure@7.25.9': resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} engines: {node: '>=6.9.0'} @@ -1076,6 +1296,10 @@ packages: resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.25.9': resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} engines: {node: '>=6.9.0'} @@ -1098,6 +1322,11 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.28.5': + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9': resolution: {integrity: sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==} engines: {node: '>=6.9.0'} @@ -1616,6 +1845,10 @@ packages: resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==} engines: {node: '>=6.9.0'} + '@babel/types@7.28.5': + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} + engines: {node: '>=6.9.0'} + '@bany/curl-to-json@1.2.8': resolution: {integrity: sha512-hPt9KUM2sGZ5Ojx3O9utjzUgjRZI3CZPAlLf+cRY9EUzVs7tWt1OpA0bhEUTX2PEEkOeyZ6sC0tAQMOHh9ld+Q==} @@ -1809,6 +2042,9 @@ packages: '@emnapi/core@1.3.1': resolution: {integrity: sha512-pVGjBIt1Y6gg3EJN8jTcfpP/+uuRksIo055oE/OBkDNcjZqVbfkWCksG1Jp4yZnj3iKWyWX8fdG/j6UDYPbFog==} + '@emnapi/core@1.7.1': + resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} + '@emnapi/runtime@1.3.1': resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} @@ -1818,6 +2054,9 @@ packages: '@emnapi/wasi-threads@1.0.1': resolution: {integrity: sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==} + '@emnapi/wasi-threads@1.1.0': + resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + '@emotion/babel-plugin@11.13.5': resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} @@ -2347,8 +2586,8 @@ packages: resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@fastgpt-sdk/plugin@0.2.16': - resolution: {integrity: sha512-tEpwtSLqPJCvvEk+KpdlgCl2N7n3m5ew2C9/hFKt+ahBY+eaU4WVrblJ6idSIImZ9lqOjOW4Mq7U1lO1mq06mQ==} + '@fastgpt-sdk/plugin@0.2.17': + resolution: {integrity: sha512-TU93FD9JIeAV+isoLVVbW+yX14J27Kgd5Sn8LPvYWkrorUEtWeVfd8rOzh/KXPd43hCgD3bSDZ1W3hC06Spnog==} '@fastify/accept-negotiator@1.1.0': resolution: {integrity: sha512-OIHZrb2ImZ7XG85HXOONLcJWGosv7sIvM2ifAPQVhg9Lv7qdmMBNVaai4QTdyuaqbKM5eO6sLSQOYI7wEQeCJQ==} @@ -2681,6 +2920,9 @@ packages: resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + '@jridgewell/gen-mapping@0.3.8': resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} @@ -2705,6 +2947,9 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} @@ -3006,6 +3251,9 @@ packages: '@napi-rs/wasm-runtime@0.2.7': resolution: {integrity: sha512-5yximcFK5FNompXfJFoWanu5l8v1hNGqNHh9du1xETp9HWk/B/PzvchX55WYOPaIeNglG8++68AAiauBAtbnzw==} + '@napi-rs/wasm-runtime@1.1.0': + resolution: {integrity: sha512-Fq6DJW+Bb5jaWE69/qOE0D1TUN9+6uWhCeZpdnSBk14pjLcCWR7Q8n49PTSPHazM37JqrsdpEthXy2xn6jWWiA==} + '@nestjs/cli@10.4.9': resolution: {integrity: sha512-s8qYd97bggqeK7Op3iD49X2MpFtW4LVNLAwXFkfbRxKME6IYT7X0muNTJ2+QfI8hpbNx9isWkrLWIp+g5FOhiA==} engines: {node: '>= 16.14'} @@ -3469,6 +3717,9 @@ packages: resolution: {integrity: sha512-jwCnuo8656McJpxvQ0UKt6C6I2oFSJOHVY69Brsbx9N1ZPrYI8/+W6uNCeqhUQEGzj9sLoCQwLZooIjSC82s8w==} engines: {node: ^18.19.0 || >=20.6.0} + '@oxc-project/types@0.101.0': + resolution: {integrity: sha512-nuFhqlUzJX+gVIPPfuE6xurd4lST3mdcWOhyK/rZO0B9XWMKm79SuszIQEnSMmmDhq1DC8WWVYGVd+6F93o1gQ==} + '@oxc-resolver/binding-darwin-arm64@5.0.0': resolution: {integrity: sha512-zwHAf+owoxSWTDD4dFuwW+FkpaDzbaL30H5Ltocb+RmLyg4WKuteusRLKh5Y8b/cyu7UzhxM0haIqQjyqA1iuA==} cpu: [arm64] @@ -3664,6 +3915,9 @@ packages: '@protobufjs/utf8@1.1.0': resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + '@quansync/fs@1.0.0': + resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} + '@reactflow/background@11.3.14': resolution: {integrity: sha512-Gewd7blEVT5Lh6jqrvOgd4G6Qk17eGKQfsDXgyRSqM+CTwDqRldG2LsWN4sNeno6sbqVIC2fZ+rAUBFA9ZEUDA==} peerDependencies: @@ -3707,6 +3961,86 @@ packages: '@codemirror/state': ^6.0.0 '@codemirror/view': ^6.0.0 + '@rolldown/binding-android-arm64@1.0.0-beta.53': + resolution: {integrity: sha512-Ok9V8o7o6YfSdTTYA/uHH30r3YtOxLD6G3wih/U9DO0ucBBFq8WPt/DslU53OgfteLRHITZny9N/qCUxMf9kjQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.0-beta.53': + resolution: {integrity: sha512-yIsKqMz0CtRnVa6x3Pa+mzTihr4Ty+Z6HfPbZ7RVbk1Uxnco4+CUn7Qbm/5SBol1JD/7nvY8rphAgyAi7Lj6Vg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.0-beta.53': + resolution: {integrity: sha512-GTXe+mxsCGUnJOFMhfGWmefP7Q9TpYUseHvhAhr21nCTgdS8jPsvirb0tJwM3lN0/u/cg7bpFNa16fQrjKrCjQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.0-beta.53': + resolution: {integrity: sha512-9Tmp7bBvKqyDkMcL4e089pH3RsjD3SUungjmqWtyhNOxoQMh0fSmINTyYV8KXtE+JkxYMPWvnEt+/mfpVCkk8w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.53': + resolution: {integrity: sha512-a1y5fiB0iovuzdbjUxa7+Zcvgv+mTmlGGC4XydVIsyl48eoxgaYkA3l9079hyTyhECsPq+mbr0gVQsFU11OJAQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.53': + resolution: {integrity: sha512-bpIGX+ov9PhJYV+wHNXl9rzq4F0QvILiURn0y0oepbQx+7stmQsKA0DhPGwmhfvF856wq+gbM8L92SAa/CBcLg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.53': + resolution: {integrity: sha512-bGe5EBB8FVjHBR1mOLOPEFg1Lp3//7geqWkU5NIhxe+yH0W8FVrQ6WRYOap4SUTKdklD/dC4qPLREkMMQ855FA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.53': + resolution: {integrity: sha512-qL+63WKVQs1CMvFedlPt0U9PiEKJOAL/bsHMKUDS6Vp2Q+YAv/QLPu8rcvkfIMvQ0FPU2WL0aX4eWwF6e/GAnA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-linux-x64-musl@1.0.0-beta.53': + resolution: {integrity: sha512-VGl9JIGjoJh3H8Mb+7xnVqODajBmrdOOb9lxWXdcmxyI+zjB2sux69br0hZJDTyLJfvBoYm439zPACYbCjGRmw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-openharmony-arm64@1.0.0-beta.53': + resolution: {integrity: sha512-B4iIserJXuSnNzA5xBLFUIjTfhNy7d9sq4FUMQY3GhQWGVhS2RWWzzDnkSU6MUt7/aHUrep0CdQfXUJI9D3W7A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.0-beta.53': + resolution: {integrity: sha512-BUjAEgpABEJXilGq/BPh7jeU3WAJ5o15c1ZEgHaDWSz3LB881LQZnbNJHmUiM4d1JQWMYYyR1Y490IBHi2FPJg==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.53': + resolution: {integrity: sha512-s27uU7tpCWSjHBnxyVXHt3rMrQdJq5MHNv3BzsewCIroIw3DJFjMH1dzCPPMUFxnh1r52Nf9IJ/eWp6LDoyGcw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.53': + resolution: {integrity: sha512-cjWL/USPJ1g0en2htb4ssMjIycc36RvdQAx1WlXnS6DpULswiUTVXPDesTifSKYSyvx24E0YqQkEm0K/M2Z/AA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.0-beta.53': + resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==} + '@rollup/rollup-android-arm-eabi@4.35.0': resolution: {integrity: sha512-uYQ2WfPaqz5QtVgMxfN6NpLD+no0MYHDBywl7itPYd3K5TjjSghNKmX8ic9S8NU8w81NVhJv/XojcHptRly7qQ==} cpu: [arm] @@ -3925,6 +4259,222 @@ packages: '@sinonjs/fake-timers@10.3.0': resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + '@smithy/abort-controller@4.2.5': + resolution: {integrity: sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA==} + 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.3': + resolution: {integrity: sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw==} + engines: {node: '>=18.0.0'} + + '@smithy/core@3.18.7': + resolution: {integrity: sha512-axG9MvKhMWOhFbvf5y2DuyTxQueO0dkedY9QC3mAfndLosRI/9LJv8WaL0mw7ubNhsO4IuXX9/9dYGPFvHrqlw==} + engines: {node: '>=18.0.0'} + + '@smithy/credential-provider-imds@4.2.5': + resolution: {integrity: sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-codec@4.2.5': + resolution: {integrity: sha512-Ogt4Zi9hEbIP17oQMd68qYOHUzmH47UkK7q7Gl55iIm9oKt27MUGrC5JfpMroeHjdkOliOA4Qt3NQ1xMq/nrlA==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-browser@4.2.5': + resolution: {integrity: sha512-HohfmCQZjppVnKX2PnXlf47CW3j92Ki6T/vkAT2DhBR47e89pen3s4fIa7otGTtrVxmj7q+IhH0RnC5kpR8wtw==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-config-resolver@4.3.5': + resolution: {integrity: sha512-ibjQjM7wEXtECiT6my1xfiMH9IcEczMOS6xiCQXoUIYSj5b1CpBbJ3VYbdwDy8Vcg5JHN7eFpOCGk8nyZAltNQ==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-node@4.2.5': + resolution: {integrity: sha512-+elOuaYx6F2H6x1/5BQP5ugv12nfJl66GhxON8+dWVUEDJ9jah/A0tayVdkLRP0AeSac0inYkDz5qBFKfVp2Gg==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-universal@4.2.5': + resolution: {integrity: sha512-G9WSqbST45bmIFaeNuP/EnC19Rhp54CcVdX9PDL1zyEB514WsDVXhlyihKlGXnRycmHNmVv88Bvvt4EYxWef/Q==} + engines: {node: '>=18.0.0'} + + '@smithy/fetch-http-handler@5.3.6': + resolution: {integrity: sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-blob-browser@4.2.6': + resolution: {integrity: sha512-8P//tA8DVPk+3XURk2rwcKgYwFvwGwmJH/wJqQiSKwXZtf/LiZK+hbUZmPj/9KzM+OVSwe4o85KTp5x9DUZTjw==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-node@4.2.5': + resolution: {integrity: sha512-DpYX914YOfA3UDT9CN1BM787PcHfWRBB43fFGCYrZFUH0Jv+5t8yYl+Pd5PW4+QzoGEDvn5d5QIO4j2HyYZQSA==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-stream-node@4.2.5': + resolution: {integrity: sha512-6+do24VnEyvWcGdHXomlpd0m8bfZePpUKBy7m311n+JuRwug8J4dCanJdTymx//8mi0nlkflZBvJe+dEO/O12Q==} + engines: {node: '>=18.0.0'} + + '@smithy/invalid-dependency@4.2.5': + resolution: {integrity: sha512-2L2erASEro1WC5nV+plwIMxrTXpvpfzl4e+Nre6vBVRR2HKeGGcvpJyyL3/PpiSg+cJG2KpTmZmq934Olb6e5A==} + 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.5': + resolution: {integrity: sha512-Bt6jpSTMWfjCtC0s79gZ/WZ1w90grfmopVOWqkI2ovhjpD5Q2XRXuecIPB9689L2+cCySMbaXDhBPU56FKNDNg==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-content-length@4.2.5': + resolution: {integrity: sha512-Y/RabVa5vbl5FuHYV2vUCwvh/dqzrEY/K2yWPSqvhFUwIY0atLqO4TienjBXakoy4zrKAMCZwg+YEqmH7jaN7A==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-endpoint@4.3.14': + resolution: {integrity: sha512-v0q4uTKgBM8dsqGjqsabZQyH85nFaTnFcgpWU1uydKFsdyyMzfvOkNum9G7VK+dOP01vUnoZxIeRiJ6uD0kjIg==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-retry@4.4.14': + resolution: {integrity: sha512-Z2DG8Ej7FyWG1UA+7HceINtSLzswUgs2np3sZX0YBBxCt+CXG4QUxv88ZDS3+2/1ldW7LqtSY1UO/6VQ1pND8Q==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-serde@4.2.6': + resolution: {integrity: sha512-VkLoE/z7e2g8pirwisLz8XJWedUSY8my/qrp81VmAdyrhi94T+riBfwP+AOEEFR9rFTSonC/5D2eWNmFabHyGQ==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-stack@4.2.5': + resolution: {integrity: sha512-bYrutc+neOyWxtZdbB2USbQttZN0mXaOyYLIsaTbJhFsfpXyGWUxJpEuO1rJ8IIJm2qH4+xJT0mxUSsEDTYwdQ==} + engines: {node: '>=18.0.0'} + + '@smithy/node-config-provider@4.3.5': + resolution: {integrity: sha512-UTurh1C4qkVCtqggI36DGbLB2Kv8UlcFdMXDcWMbqVY2uRg0XmT9Pb4Vj6oSQ34eizO1fvR0RnFV4Axw4IrrAg==} + engines: {node: '>=18.0.0'} + + '@smithy/node-http-handler@4.4.5': + resolution: {integrity: sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw==} + engines: {node: '>=18.0.0'} + + '@smithy/property-provider@4.2.5': + resolution: {integrity: sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg==} + engines: {node: '>=18.0.0'} + + '@smithy/protocol-http@5.3.5': + resolution: {integrity: sha512-RlaL+sA0LNMp03bf7XPbFmT5gN+w3besXSWMkA8rcmxLSVfiEXElQi4O2IWwPfxzcHkxqrwBFMbngB8yx/RvaQ==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-builder@4.2.5': + resolution: {integrity: sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-parser@4.2.5': + resolution: {integrity: sha512-031WCTdPYgiQRYNPXznHXof2YM0GwL6SeaSyTH/P72M1Vz73TvCNH2Nq8Iu2IEPq9QP2yx0/nrw5YmSeAi/AjQ==} + engines: {node: '>=18.0.0'} + + '@smithy/service-error-classification@4.2.5': + resolution: {integrity: sha512-8fEvK+WPE3wUAcDvqDQG1Vk3ANLR8Px979te96m84CbKAjBVf25rPYSzb4xU4hlTyho7VhOGnh5i62D/JVF0JQ==} + engines: {node: '>=18.0.0'} + + '@smithy/shared-ini-file-loader@4.4.0': + resolution: {integrity: sha512-5WmZ5+kJgJDjwXXIzr1vDTG+RhF9wzSODQBfkrQ2VVkYALKGvZX1lgVSxEkgicSAFnFhPj5rudJV0zoinqS0bA==} + engines: {node: '>=18.0.0'} + + '@smithy/signature-v4@5.3.5': + resolution: {integrity: sha512-xSUfMu1FT7ccfSXkoLl/QRQBi2rOvi3tiBZU2Tdy3I6cgvZ6SEi9QNey+lqps/sJRnogIS+lq+B1gxxbra2a/w==} + engines: {node: '>=18.0.0'} + + '@smithy/smithy-client@4.9.10': + resolution: {integrity: sha512-Jaoz4Jw1QYHc1EFww/E6gVtNjhoDU+gwRKqXP6C3LKYqqH2UQhP8tMP3+t/ePrhaze7fhLE8vS2q6vVxBANFTQ==} + engines: {node: '>=18.0.0'} + + '@smithy/types@4.9.0': + resolution: {integrity: sha512-MvUbdnXDTwykR8cB1WZvNNwqoWVaTRA0RLlLmf/cIFNMM2cKWz01X4Ly6SMC4Kks30r8tT3Cty0jmeWfiuyHTA==} + engines: {node: '>=18.0.0'} + + '@smithy/url-parser@4.2.5': + resolution: {integrity: sha512-VaxMGsilqFnK1CeBX+LXnSuaMx4sTL/6znSZh2829txWieazdVxr54HmiyTsIbpOTLcf5nYpq9lpzmwRdxj6rQ==} + 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.13': + resolution: {integrity: sha512-hlVLdAGrVfyNei+pKIgqDTxfu/ZI2NSyqj4IDxKd5bIsIqwR/dSlkxlPaYxFiIaDVrBy0he8orsFy+Cz119XvA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-node@4.2.16': + resolution: {integrity: sha512-F1t22IUiJLHrxW9W1CQ6B9PN+skZ9cqSuzB18Eh06HrJPbjsyZ7ZHecAKw80DQtyGTRcVfeukKaCRYebFwclbg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-endpoints@3.2.5': + resolution: {integrity: sha512-3O63AAWu2cSNQZp+ayl9I3NapW1p1rR5mlVHcF6hAB1dPZUQFfRPYtplWX/3xrzWthPGj5FqB12taJJCfH6s8A==} + 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.5': + resolution: {integrity: sha512-6Y3+rvBF7+PZOc40ybeZMcGln6xJGVeY60E7jy9Mv5iKpMJpHgRE6dKy9ScsVxvfAYuEX4Q9a65DQX90KaQ3bA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-retry@4.2.5': + resolution: {integrity: sha512-GBj3+EZBbN4NAqJ/7pAhsXdfzdlznOh8PydUijy6FpNIMnHPSMO2/rP4HKu+UFeikJxShERk528oy7GT79YiJg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-stream@4.5.6': + resolution: {integrity: sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ==} + 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.5': + resolution: {integrity: sha512-Dbun99A3InifQdIrsXZ+QLcC0PGBPAdrl4cj1mTgJvyc9N2zf7QSxg8TBkzsCmGJdE3TLbO9ycwpY0EkWahQ/g==} + engines: {node: '>=18.0.0'} + + '@smithy/uuid@1.1.0': + resolution: {integrity: sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==} + engines: {node: '>=18.0.0'} + '@svgr/babel-plugin-add-jsx-attribute@6.5.1': resolution: {integrity: sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ==} engines: {node: '>=10'} @@ -4042,6 +4592,9 @@ packages: '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + '@tootallnate/quickjs-emscripten@0.23.0': + resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} + '@trysound/sax@0.2.0': resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} @@ -4069,9 +4622,15 @@ packages: '@tsconfig/node16@1.0.4': resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@tybys/wasm-util@0.9.0': resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} + '@types/ali-oss@6.16.13': + resolution: {integrity: sha512-Nxxs9JYESnJcVBI9mNv+dFNnbdz15tKS15mwckZqSIM75ttb8GcNYgeNfKG9gsykSIDpbSqcSnEqxdV5vSlbDg==} + '@types/async-retry@1.4.9': resolution: {integrity: sha512-s1ciZQJzRh3708X/m3vPExr5KJlzlZJvXsKpbtE2luqNcbROr64qU+3KpJsYHqWMeaxI839OvXf9PrUSw1Xtyg==} @@ -4798,10 +5357,18 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + address@1.2.2: + resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==} + engines: {node: '>= 10.0.0'} + agent-base@7.1.3: resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} engines: {node: '>= 14'} + agentkeepalive@3.5.3: + resolution: {integrity: sha512-yqXL+k5rr8+ZRpOAntkaaRgWgE5o8ESAj5DyRmVTCSoZxXmqemb9Dd7T4i5UzwuERdLAJUy6XzR9zFVuf0kzkw==} + engines: {node: '>= 4.0.0'} + agentkeepalive@4.6.0: resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} engines: {node: '>= 8.0.0'} @@ -4825,6 +5392,14 @@ packages: ajv: optional: true + ajv-formats@1.6.1: + resolution: {integrity: sha512-4CjkH20If1lhR5CGtqkrVg3bbOtFEG80X9v6jDOIUhbzzbB+UzPBGy8GQhUNVZ0yvMHdMpawCOcy5ydGMsagGQ==} + peerDependencies: + ajv: ^7.0.0 + peerDependenciesMeta: + ajv: + optional: true + ajv-formats@2.1.1: resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependencies: @@ -4854,12 +5429,19 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@7.2.4: + resolution: {integrity: sha512-nBeQgg/ZZA3u3SYxyaDvpvDtgZ/EZPF547ARgZBrG9Bhu1vKDwAIjtIf+sDtJUKa2zOcEbmRLBRSyMraS/Oy1A==} + ajv@8.12.0: resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} ajv@8.17.1: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + ali-oss@6.23.0: + resolution: {integrity: sha512-FipRmyd16Pr/tEey/YaaQ/24Pc3HEpLM9S1DRakEuXlSLXNIJnu1oJtHM53eVYpvW3dXapSjrip3xylZUTIZVQ==} + engines: {node: '>=8'} + ansi-align@3.0.1: resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} @@ -4899,6 +5481,10 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + ansis@4.2.0: + resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} + engines: {node: '>=14'} + any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} @@ -4974,6 +5560,13 @@ packages: asap@2.0.6: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + asn1@0.2.6: + resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} + + assert-plus@1.0.0: + resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} + engines: {node: '>=0.8'} + assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} @@ -4981,9 +5574,17 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + ast-kit@2.2.0: + resolution: {integrity: sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==} + engines: {node: '>=20.19.0'} + ast-types-flow@0.0.8: resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + ast-types@0.13.4: + resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} + engines: {node: '>=4'} + async-function@1.0.0: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} @@ -5001,6 +5602,10 @@ packages: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} + atomically@1.7.0: + resolution: {integrity: sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==} + engines: {node: '>=10.12.0'} + available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -5008,10 +5613,16 @@ packages: avvio@8.4.0: resolution: {integrity: sha512-CDSwaxINFy59iNwhYnkvALBwZiTydGkOecZyPkqBpABYR1KqGEsET0VOOYDwtleZSUIdeY36DC2bSZ24CO1igA==} + aws-sign2@0.7.0: + resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} + aws-ssl-profiles@1.1.2: resolution: {integrity: sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==} engines: {node: '>= 6.0.0'} + aws4@1.13.2: + resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==} + axe-core@4.10.3: resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==} engines: {node: '>=4'} @@ -5085,10 +5696,20 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + basic-ftp@5.0.5: + resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} + engines: {node: '>=10.0.0'} + + bcrypt-pbkdf@1.0.2: + resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} + birpc@3.0.0: + resolution: {integrity: sha512-by+04pHuxpCEQcucAXqzopqfhyI8TLK5Qg5MST0cB6MP+JhHna9ollrtK9moVh27aq6Q6MEJgebD0cVm//yBkg==} + bl@1.2.3: resolution: {integrity: sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==} @@ -5115,6 +5736,12 @@ packages: boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + bowser@1.9.4: + resolution: {integrity: sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==} + + bowser@2.13.1: + resolution: {integrity: sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw==} + boxen@7.1.1: resolution: {integrity: sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==} engines: {node: '>=14.16'} @@ -5170,12 +5797,18 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + buffer@5.6.0: + resolution: {integrity: sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==} + buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + builtin-status-codes@3.0.0: + resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==} + bullmq@5.52.2: resolution: {integrity: sha512-fK/dKIv8ymyys4K+zeNEPA+yuYWzRPmBWUmwIMz8DvYekadl8VG19yUx94Na0n0cLAi+spdn3a/+ufkYK7CBUg==} @@ -5250,6 +5883,9 @@ packages: caniuse-lite@1.0.30001757: resolution: {integrity: sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==} + caseless@0.12.0: + resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} + ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -5506,6 +6142,10 @@ packages: resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==} engines: {'0': node >= 6.0} + conf@9.0.2: + resolution: {integrity: sha512-rLSiilO85qHgaTBIIHQpsv8z+NnVfZq3cKuYNCXN1AOqPzced0GWZEe/A517VldRLyQYXUMyV+vszavE2jSAqw==} + engines: {node: '>=10'} + confbox@0.1.8: resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} @@ -5558,12 +6198,18 @@ packages: copy-to-clipboard@3.3.3: resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} + copy-to@2.0.1: + resolution: {integrity: sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w==} + core-js-compat@3.41.0: resolution: {integrity: sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==} core-js@3.41.0: resolution: {integrity: sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==} + core-util-is@1.0.2: + resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} + core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -5571,6 +6217,10 @@ packages: resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} engines: {node: '>= 0.10'} + cos-nodejs-sdk-v5@2.15.4: + resolution: {integrity: sha512-TP/iYTvKKKhRK89on9SRfSMGEw/9SFAAU8EC1kdT5Fmpx7dAwaCNM2+R2H1TSYoQt+03rwOs8QEfNkX8GOHjHQ==} + engines: {node: '>= 6'} + cose-base@1.0.3: resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} @@ -5801,6 +6451,14 @@ packages: damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + dashdash@1.14.1: + resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} + engines: {node: '>=0.10'} + + data-uri-to-buffer@6.0.2: + resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} + engines: {node: '>= 14'} + data-view-buffer@1.0.2: resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} engines: {node: '>= 0.4'} @@ -5817,9 +6475,16 @@ packages: resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} engines: {node: '>=0.11'} + dateformat@2.2.0: + resolution: {integrity: sha512-GODcnWq3YGoTnygPfi02ygEiRxqUxpJwuRHjdhJYuxpcZmDq4rjBiXYmbCCzStxo176ixfLT6i4NPwQooRySnw==} + dayjs@1.11.13: resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + debounce-fn@4.0.0: + resolution: {integrity: sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==} + engines: {node: '>=10'} + debounce@1.2.1: resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} @@ -5940,6 +6605,10 @@ packages: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} + default-user-agent@1.0.0: + resolution: {integrity: sha512-bDF7bg6OSNcSwFWPu4zYKpVkJZQYVrAANMYB8bc9Szem1D0yKdm4sa/rOCs2aC9+2GMqQ7KnwtZRvDhmLF0dXw==} + engines: {node: '>= 0.10.0'} + defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} @@ -5958,6 +6627,10 @@ packages: defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + degenerator@5.0.1: + resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} + engines: {node: '>= 14'} + delaunator@5.0.1: resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} @@ -6022,6 +6695,10 @@ packages: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} + digest-header@1.1.0: + resolution: {integrity: sha512-glXVh42vz40yZb9Cq2oMOt70FIoWiv+vxNvdKdU8CwjLad25qHM3trLxhl9bVjdr6WaslIXhWpn0NO8T/67Qjg==} + engines: {node: '>= 8.0.0'} + dijkstrajs@1.0.3: resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==} @@ -6087,6 +6764,15 @@ packages: resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} engines: {node: '>=12'} + dts-resolver@2.1.3: + resolution: {integrity: sha512-bihc7jPC90VrosXNzK0LTE2cuLP6jr0Ro8jk+kMugHReJVLIpHz/xadeq3MhuwyO4TD4OA3L1Q8pBBFRc08Tsw==} + engines: {node: '>=20.19.0'} + peerDependencies: + oxc-resolver: '>=11.0.0' + peerDependenciesMeta: + oxc-resolver: + optional: true + duck@0.1.12: resolution: {integrity: sha512-wkctla1O6VfP89gQ+J/yDesM0S7B7XLXjKGzXxMDVFg7uEn706niAtyYovKbyq1oT9YwDcly721/iUWoc8MVRg==} @@ -6100,6 +6786,9 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + ecc-jsbn@0.1.2: + resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} + ecdsa-sig-formatter@1.0.11: resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} @@ -6138,6 +6827,10 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + empathic@2.0.0: + resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} + engines: {node: '>=14'} + enabled@2.0.0: resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} @@ -6155,6 +6848,10 @@ packages: end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + end-or-error@1.0.1: + resolution: {integrity: sha512-OclLMSug+k2A0JKuf494im25ANRBVW8qsjmwbgX7lQ8P82H21PQ1PWkoYwb9y5yMBS69BPlwtzdIFClo3+7kOQ==} + engines: {node: '>= 0.11.14'} + enhanced-resolve@5.18.1: resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} engines: {node: '>=10.13.0'} @@ -6211,6 +6908,9 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} + es-toolkit@1.43.0: + resolution: {integrity: sha512-SKCT8AsWvYzBBuUqMk4NPwFlSdqLpJwmy6AP322ERn8W2YLIB6JBXnwMI2Qsh2gfphT3q7EKAxKb23cvFHFwKA==} + esbuild@0.21.5: resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} @@ -6253,6 +6953,11 @@ packages: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + eslint-config-next@14.2.26: resolution: {integrity: sha512-KZNh1xvWG1ZDFD2f2WkvvnMpp7Sjsl6xJXCsvfEe8GH1FLXn6GtXo7lY9S8xDcn6oBWmKA0hSrlrp1DNQ9QDnQ==} peerDependencies: @@ -6469,6 +7174,10 @@ packages: resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} engines: {node: '>= 18'} + extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -6476,6 +7185,10 @@ packages: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} + extsprintf@1.3.0: + resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} + engines: {'0': node >=0.6.0} + fast-content-type-parse@1.1.0: resolution: {integrity: sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==} @@ -6521,10 +7234,18 @@ packages: fast-uri@3.0.6: resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} + fast-xml-parser@4.2.5: + resolution: {integrity: sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==} + hasBin: true + fast-xml-parser@4.5.3: resolution: {integrity: sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==} hasBin: true + fast-xml-parser@5.2.5: + resolution: {integrity: sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==} + hasBin: true + fastify-plugin@4.5.1: resolution: {integrity: sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==} @@ -6554,6 +7275,15 @@ packages: picomatch: optional: true + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + fecha@4.2.3: resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} @@ -6611,6 +7341,10 @@ packages: find-root@1.1.0: resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} + find-up@3.0.0: + resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} + engines: {node: '>=6'} + find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -6653,6 +7387,9 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} + forever-agent@0.6.1: + resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} + fork-ts-checker-webpack-plugin@9.0.2: resolution: {integrity: sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==} engines: {node: '>=12.13.0', yarn: '>=1.0.0'} @@ -6667,6 +7404,10 @@ packages: resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} engines: {node: '>= 14.17'} + form-data@2.3.3: + resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} + engines: {node: '>= 0.12'} + form-data@4.0.4: resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} engines: {node: '>= 6'} @@ -6683,6 +7424,9 @@ packages: resolution: {integrity: sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==} deprecated: 'ACTION REQUIRED: SWITCH TO v3 - v1 and v2 are VULNERABLE! v1 is DEPRECATED FOR OVER 2 YEARS! Use formidable@latest or try formidable-mini for fresh projects' + formstream@1.5.2: + resolution: {integrity: sha512-NASf0lgxC1AyKNXQIrXTEYkiX99LhCEXTkiGObXAkpBui86a4u8FjH1o2bGb3PpqI3kafC+yw4zWeK6l6VHTgg==} + forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -6782,6 +7526,9 @@ packages: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} + get-ready@1.0.0: + resolution: {integrity: sha512-mFXCZPJIlcYcth+N8267+mghfYN9h3EhsDa6JSnbA3Wrhh/XFpuowviFcsDeYZtKspQyWyJqfs4O6P8CHeTwzw==} + get-stream@2.3.1: resolution: {integrity: sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==} engines: {node: '>=0.10.0'} @@ -6805,6 +7552,16 @@ packages: get-tsconfig@4.10.0: resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} + get-tsconfig@4.13.0: + resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} + + get-uri@6.0.5: + resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==} + engines: {node: '>= 14'} + + getpass@0.1.7: + resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} + github-from-package@0.0.0: resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} @@ -6876,6 +7633,15 @@ packages: resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} engines: {node: '>=10'} + har-schema@2.0.0: + resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==} + engines: {node: '>=4'} + + har-validator@5.1.5: + resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==} + engines: {node: '>=6'} + deprecated: this library is no longer supported + has-bigints@1.1.0: resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} engines: {node: '>= 0.4'} @@ -7037,6 +7803,10 @@ packages: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} + http-signature@1.2.0: + resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} + engines: {node: '>=0.8', npm: '>=1.3.7'} + http2-wrapper@2.2.1: resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} engines: {node: '>=10.19.0'} @@ -7118,6 +7888,10 @@ packages: engines: {node: '>=8'} hasBin: true + import-without-cache@0.2.3: + resolution: {integrity: sha512-roCvX171VqJ7+7pQt1kSRfwaJvFAC2zhThJWXal1rN8EqzPS3iapkAoNpHh4lM8Na1BDen+n9rVfo73RN+Y87g==} + engines: {node: '>=20.19.0'} + imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -7246,6 +8020,9 @@ packages: resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} hasBin: true + is-class-hotfix@0.0.6: + resolution: {integrity: sha512-0n+pzCC6ICtVr/WXnN2f03TK/3BfXY7me4cjCAqT8TYXEl0+JBRoqBo94JJHXcyDSLUeWbNX8Fvy5g5RJdAstQ==} + is-core-module@2.16.1: resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} engines: {node: '>= 0.4'} @@ -7264,6 +8041,10 @@ packages: is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -7402,6 +8183,9 @@ packages: resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} engines: {node: '>= 0.4'} + is-type-of@1.4.0: + resolution: {integrity: sha512-EddYllaovi5ysMLMEN7yzHEKh8A850cZ7pykrY1aNRQGn/CDjRDE9qEWbIdt7xGEVJmjBXzU/fNnC4ABTm8tEQ==} + is-typed-array@1.1.15: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} @@ -7459,6 +8243,9 @@ packages: isomorphic.js@0.2.5: resolution: {integrity: sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==} + isstream@0.1.2: + resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} + istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} @@ -7654,6 +8441,9 @@ packages: jose@6.1.3: resolution: {integrity: sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==} + js-base64@2.6.4: + resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==} + js-base64@3.7.8: resolution: {integrity: sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==} @@ -7679,6 +8469,9 @@ packages: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true + jsbn@0.1.1: + resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} + jsbn@1.1.0: resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} @@ -7715,6 +8508,12 @@ packages: json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-schema-typed@7.0.3: + resolution: {integrity: sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==} + + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -7722,6 +8521,9 @@ packages: resolution: {integrity: sha512-q3PN0lbUdv0pmurkBNdJH3pfFvOTL/Zp0lquqpvcjfKzt6Y0j49EPHAmVHCAS4Ceq/Y+PejWTzyiVpoY71+D6g==} engines: {node: '>= 4'} + json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + json5@1.0.2: resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} hasBin: true @@ -7758,6 +8560,13 @@ packages: resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} engines: {node: '>=12', npm: '>=6'} + jsprim@1.4.2: + resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} + engines: {node: '>=0.6.0'} + + jstoxml@2.2.9: + resolution: {integrity: sha512-OYWlK0j+roh+eyaMROlNbS5cd5R25Y+IUpdl7cNdB8HNrkgwQzIS7L9MegxOiWNBj9dQhA/yAxiMwCC5mwNoBw==} + jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} @@ -7955,6 +8764,10 @@ packages: resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} engines: {node: '>=14'} + locate-path@3.0.0: + resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} + engines: {node: '>=6'} + locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -8084,6 +8897,9 @@ packages: magic-string@0.30.19: resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + magic-string@0.30.8: resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==} engines: {node: '>=12'} @@ -8423,10 +9239,19 @@ packages: engines: {node: '>=10.0.0'} hasBin: true + mime@4.1.0: + resolution: {integrity: sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw==} + engines: {node: '>=16'} + hasBin: true + mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} + mimic-fn@3.1.0: + resolution: {integrity: sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==} + engines: {node: '>=8'} + mimic-fn@4.0.0: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} @@ -8657,6 +9482,10 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + netmask@2.0.2: + resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} + engines: {node: '>= 0.4.0'} + new-find-package-json@2.0.0: resolution: {integrity: sha512-lDcBsjBSMlj3LXH2v/FW3txlh2pYTjmbOXPYJD93HI5EwuLzI11tdHSIpUMmfq/IOsldj4Ps8M8flhm+pCK4Ew==} engines: {node: '>=12.22.0'} @@ -8673,6 +9502,7 @@ packages: next@14.2.33: resolution: {integrity: sha512-GiKHLsD00t4ACm1p00VgrI0rUFAC9cRDGReKyERlM57aeEZkOQGcZTpIbsGn0b562FTPJWmYfKwplfO9EaT6ng==} engines: {node: '>=18.17.0'} + deprecated: This version has a security vulnerability. Please upgrade to a patched version. See https://nextjs.org/blog/security-update-2025-12-11 for more details. hasBin: true peerDependencies: '@opentelemetry/api': ^1.1.0 @@ -8777,6 +9607,10 @@ packages: engines: {node: ^16.14.0 || >=18.0.0} hasBin: true + node-hex@1.0.1: + resolution: {integrity: sha512-iwpZdvW6Umz12ICmu9IYPRxg0tOLGmU3Tq2tKetejCj3oZd7b2nUXwP3a7QA5M9glWy8wlPS1G3RwM/CdsUbdQ==} + engines: {node: '>=8.0.0'} + node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} @@ -8818,6 +9652,9 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + oauth-sign@0.9.0: + resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -8860,6 +9697,9 @@ packages: obuf@1.1.2: resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + on-exit-leak-free@2.1.2: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} @@ -8925,10 +9765,20 @@ packages: resolution: {integrity: sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==} engines: {node: '>=16'} + os-name@1.0.3: + resolution: {integrity: sha512-f5estLO2KN8vgtTRaILIgEGBoBrMnZ3JQ7W9TMZCnOIGwHe8TRGSpcagnWDo+Dfhd/z08k9Xe75hvciJJ8Qaew==} + engines: {node: '>=0.10.0'} + hasBin: true + os-tmpdir@1.0.2: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} engines: {node: '>=0.10.0'} + osx-release@1.1.0: + resolution: {integrity: sha512-ixCMMwnVxyHFQLQnINhmIpWqXIfS2YOXchwQrk+OFzmo6nDjQ0E4KXAyyUh0T0MZgV4bUhkRrAbVqlE4yLVq4A==} + engines: {node: '>=0.10.0'} + hasBin: true + otlp-logger@1.1.10: resolution: {integrity: sha512-/8sCaoUJQ9Cqqz2bVTC5bfYeRs9SLIvr0BgPj4XXhD+1YuLhCDsBqVT8I9H8I4dnirSwgHcXjgQUNoAo889GqA==} @@ -8959,6 +9809,10 @@ packages: resolution: {integrity: sha512-ATHLtwoTNDloHRFFxFJdHnG6n2WUeFjaR8XQMFdKIv0xkXjrER8/iG9iu265jOM95zXHAfv9oTkqhrfbIzosrQ==} engines: {node: '>=20'} + p-locate@3.0.0: + resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} + engines: {node: '>=6'} + p-locate@4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} @@ -8975,6 +9829,14 @@ packages: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} + pac-proxy-agent@7.2.0: + resolution: {integrity: sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==} + engines: {node: '>= 14'} + + pac-resolver@7.0.1: + resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} + engines: {node: '>= 14'} + package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} @@ -9022,6 +9884,10 @@ packages: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} + path-exists@3.0.0: + resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} + engines: {node: '>=4'} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -9074,6 +9940,9 @@ packages: resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} engines: {node: '>= 14.16'} + pause-stream@0.0.11: + resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==} + pdfjs-dist@4.10.38: resolution: {integrity: sha512-/Y3fcFrXEAsMjJXeL9J8+ZG9U01LbuWaYypvDW2ycW1jL269L3js3DVBjDJ0Up9Np1uqDXsDrRihHANhZOlwdQ==} engines: {node: '>=20'} @@ -9085,6 +9954,9 @@ packages: pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + performance-now@2.1.0: + resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} + pg-cloudflare@1.1.1: resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==} @@ -9142,6 +10014,10 @@ packages: resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} engines: {node: '>=12'} + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + pidtree@0.6.0: resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} engines: {node: '>=0.10'} @@ -9193,6 +10069,13 @@ packages: pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + pkg-up@3.1.0: + resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==} + engines: {node: '>=8'} + + platform@1.3.6: + resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==} + pluralize@8.0.0: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} @@ -9372,9 +10255,16 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} + proxy-agent@6.5.0: + resolution: {integrity: sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==} + engines: {node: '>= 14'} + proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + psl@1.15.0: + resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} + pump@3.0.2: resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} @@ -9398,6 +10288,13 @@ packages: resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} engines: {node: '>=0.6'} + qs@6.5.3: + resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==} + engines: {node: '>=0.6'} + + quansync@1.0.0: + resolution: {integrity: sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==} + query-string@7.1.3: resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==} engines: {node: '>=6'} @@ -9745,6 +10642,11 @@ packages: request-ip@3.3.0: resolution: {integrity: sha512-cA6Xh6e0fDBBBwH77SLJaJPBmD3nWVAcF9/XAcsrIHdjhFzFiB5aNQFytdjCGPezU3ROwrR11IddKAM08vohxA==} + request@2.88.2: + resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==} + engines: {node: '>= 6'} + deprecated: request has been deprecated, see https://github.com/request/request/issues/3142 + require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -9834,6 +10736,30 @@ packages: robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} + rolldown-plugin-dts@0.18.3: + resolution: {integrity: sha512-rd1LZ0Awwfyn89UndUF/HoFF4oH9a5j+2ZeuKSJYM80vmeN/p0gslYMnHTQHBEXPhUlvAlqGA3tVgXB/1qFNDg==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@ts-macro/tsc': ^0.3.6 + '@typescript/native-preview': '>=7.0.0-dev.20250601.1' + rolldown: ^1.0.0-beta.51 + typescript: ^5.0.0 + vue-tsc: ~3.1.0 + peerDependenciesMeta: + '@ts-macro/tsc': + optional: true + '@typescript/native-preview': + optional: true + typescript: + optional: true + vue-tsc: + optional: true + + rolldown@1.0.0-beta.53: + resolution: {integrity: sha512-Qd9c2p0XKZdgT5AYd+KgAMggJ8ZmCs3JnS9PTMWkyUfteKlfmKtxJbWTHkVakxwXs1Ub7jrRYVeFeF7N0sQxyw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + rollup@4.35.0: resolution: {integrity: sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -9921,6 +10847,9 @@ packages: resolution: {integrity: sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==} engines: {node: '>=0.10.0'} + sdk-base@2.0.1: + resolution: {integrity: sha512-eeG26wRwhtwYuKGCDM3LixCaxY27Pa/5lK4rLKhQa7HBjJ3U3Y+f81MMZQRsDw/8SC2Dao/83yJTXJ8aULuN8Q==} + secure-json-parse@2.7.0: resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} @@ -9932,6 +10861,10 @@ packages: resolution: {integrity: sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==} engines: {node: '>=12'} + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -10137,6 +11070,11 @@ packages: resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==} engines: {node: '>= 0.6'} + sshpk@1.18.0: + resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} + engines: {node: '>=0.10.0'} + hasBin: true + ssri@10.0.6: resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -10167,6 +11105,10 @@ packages: state-toggle@1.0.3: resolution: {integrity: sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==} + statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + statuses@2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} @@ -10182,12 +11124,22 @@ packages: resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + stream-browserify@3.0.0: + resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} + stream-chain@2.2.5: resolution: {integrity: sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==} + stream-http@2.8.2: + resolution: {integrity: sha512-QllfrBhqF1DPcz46WxKTs6Mz1Bpc+8Qm6vbqOpVav5odAXwbyzwnEczoWqtxrsmlO+cJqtPrp/8gWKWjaKLLlA==} + stream-json@1.9.1: resolution: {integrity: sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==} + stream-wormhole@1.1.0: + resolution: {integrity: sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==} + engines: {node: '>=4.0.0'} + streamsearch@1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} @@ -10296,6 +11248,9 @@ packages: strnum@1.1.2: resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==} + strnum@2.1.2: + resolution: {integrity: sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==} + strtok3@9.1.1: resolution: {integrity: sha512-FhwotcEqjr241ZbjFzjlIYg6c5/L/s4yBGWSMvJ9UoExiSqL+FnFA/CaeZx17WGaZMS/4SOZp8wH18jSS4R4lw==} engines: {node: '>=16'} @@ -10500,10 +11455,18 @@ packages: tinyexec@0.3.2: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + tinyexec@1.0.2: + resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} + engines: {node: '>=18'} + tinyglobby@0.2.12: resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} engines: {node: '>=12.0.0'} + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + tinypool@0.8.4: resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} engines: {node: '>=14.0.0'} @@ -10531,6 +11494,9 @@ packages: tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + to-arraybuffer@1.0.1: + resolution: {integrity: sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==} + to-buffer@1.1.1: resolution: {integrity: sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==} @@ -10557,6 +11523,10 @@ packages: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} + tough-cookie@2.5.0: + resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} + engines: {node: '>=0.8'} + tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} @@ -10661,6 +11631,32 @@ packages: resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} engines: {node: '>=6'} + tsdown@0.17.4: + resolution: {integrity: sha512-z+kNuv1rwM1POQIufDUVrdNc/uGy0ueRVafCyDH39IdHxin4JXgB8DNGSPoqdIpcOpqUoRbNreK8NxENFmlhKw==} + engines: {node: '>=20.19.0'} + deprecated: Including an unexpected breaking change (copy behavior) + hasBin: true + peerDependencies: + '@arethetypeswrong/core': ^0.18.1 + '@vitejs/devtools': ^0.0.0-alpha.19 + publint: ^0.3.0 + typescript: ^5.0.0 + unplugin-lightningcss: ^0.4.0 + unplugin-unused: ^0.5.0 + peerDependenciesMeta: + '@arethetypeswrong/core': + optional: true + '@vitejs/devtools': + optional: true + publint: + optional: true + typescript: + optional: true + unplugin-lightningcss: + optional: true + unplugin-unused: + optional: true + tslib@2.3.0: resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==} @@ -10685,6 +11681,9 @@ packages: turndown@7.2.0: resolution: {integrity: sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==} + tweetnacl@0.14.5: + resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -10757,6 +11756,11 @@ packages: engines: {node: '>=14.17'} hasBin: true + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + ufo@1.5.4: resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} @@ -10775,6 +11779,9 @@ packages: unbzip2-stream@1.4.3: resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} + unconfig-core@7.4.2: + resolution: {integrity: sha512-VgPCvLWugINbXvMQDf8Jh0mlbvNjNC6eSUziHsBCMpxR05OPrNrvDnyatdMjRgcHaaNsCqz+wjNXxNw1kRLHUg==} + underscore@1.13.7: resolution: {integrity: sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==} @@ -10790,6 +11797,10 @@ packages: undici-types@7.8.0: resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==} + unescape@1.0.1: + resolution: {integrity: sha512-O0+af1Gs50lyH1nUu3ZyYS1cRh01Q/kUKatTOkSs7jukXE6/NebucDVxyiDsA9AQ4JC1V1jUH9EO8JX2nMDgGQ==} + engines: {node: '>=0.10.0'} + unhead@1.11.20: resolution: {integrity: sha512-3AsNQC0pjwlLqEYHLjtichGWankK8yqmocReITecmpB1H0aOabeESueyy+8X1gyJx4ftZVwo9hqQ4O3fPWffCA==} @@ -10877,6 +11888,16 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} + unrun@0.2.19: + resolution: {integrity: sha512-DbwbJ9BvPEb3BeZnIpP9S5tGLO/JIgPQ3JrpMRFIfZMZfMG19f26OlLbC2ml8RRdrI2ZA7z2t+at5tsIHbh6Qw==} + engines: {node: '>=20.19.0'} + hasBin: true + peerDependencies: + synckit: ^0.11.11 + peerDependenciesMeta: + synckit: + optional: true + update-browserslist-db@1.1.3: resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} hasBin: true @@ -10890,6 +11911,15 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + urllib@2.44.0: + resolution: {integrity: sha512-zRCJqdfYllRDA9bXUtx+vccyRqtJPKsw85f44zH7zPD28PIvjMqIgw9VwoTLV7xTBWZsbebUFVHU5ghQcWku2A==} + engines: {node: '>= 0.10.0'} + peerDependencies: + proxy-agent: ^5.0.0 + peerDependenciesMeta: + proxy-agent: + optional: true + use-callback-ref@1.3.3: resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} engines: {node: '>=10'} @@ -10966,10 +11996,19 @@ packages: util@0.12.5: resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + utility@1.18.0: + resolution: {integrity: sha512-PYxZDA+6QtvRvm//++aGdmKG/cI07jNwbROz0Ql+VzFV1+Z0Dy55NI4zZ7RHc9KKpBePNFwoErqIuqQv/cjiTA==} + engines: {node: '>= 0.12.0'} + utils-merge@1.0.1: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} + uuid@3.4.0: + resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} + deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. + hasBin: true + uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true @@ -10994,6 +12033,10 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} + verror@1.10.0: + resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} + engines: {'0': node >=0.6.0} + vfile-location@2.0.6: resolution: {integrity: sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==} @@ -11296,6 +12339,10 @@ packages: resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} engines: {node: '>=12'} + win-release@1.1.1: + resolution: {integrity: sha512-iCRnKVvGxOQdsKhcQId2PXV1vV3J/sDPXKA4Oe9+Eti2nb2ESEsYHRYls/UjoUW3bIc5ZDO8dTH50A/5iVN+bw==} + engines: {node: '>=0.10.0'} + winston-transport@4.9.0: resolution: {integrity: sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==} engines: {node: '>= 12.0.0'} @@ -11469,9 +12516,6 @@ packages: zod@3.24.1: resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==} - zod@3.25.51: - resolution: {integrity: sha512-TQSnBldh+XSGL+opiSIq0575wvDPqu09AqWe1F7JhUMKY+M91/aGlK4MhpVNO7MgYfHcVCB1ffwAUTJzllKJqg==} - zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} @@ -11567,6 +12611,514 @@ snapshots: call-me-maybe: 1.0.2 openapi-types: 12.1.3 + '@aws-crypto/crc32@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.936.0 + tslib: 2.8.1 + + '@aws-crypto/crc32c@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.936.0 + 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.936.0 + '@aws-sdk/util-locate-window': 3.893.0 + '@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.936.0 + '@aws-sdk/util-locate-window': 3.893.0 + '@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.936.0 + 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.936.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-sdk/client-s3@3.948.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.947.0 + '@aws-sdk/credential-provider-node': 3.948.0 + '@aws-sdk/middleware-bucket-endpoint': 3.936.0 + '@aws-sdk/middleware-expect-continue': 3.936.0 + '@aws-sdk/middleware-flexible-checksums': 3.947.0 + '@aws-sdk/middleware-host-header': 3.936.0 + '@aws-sdk/middleware-location-constraint': 3.936.0 + '@aws-sdk/middleware-logger': 3.936.0 + '@aws-sdk/middleware-recursion-detection': 3.948.0 + '@aws-sdk/middleware-sdk-s3': 3.947.0 + '@aws-sdk/middleware-ssec': 3.936.0 + '@aws-sdk/middleware-user-agent': 3.947.0 + '@aws-sdk/region-config-resolver': 3.936.0 + '@aws-sdk/signature-v4-multi-region': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@aws-sdk/util-endpoints': 3.936.0 + '@aws-sdk/util-user-agent-browser': 3.936.0 + '@aws-sdk/util-user-agent-node': 3.947.0 + '@smithy/config-resolver': 4.4.3 + '@smithy/core': 3.18.7 + '@smithy/eventstream-serde-browser': 4.2.5 + '@smithy/eventstream-serde-config-resolver': 4.3.5 + '@smithy/eventstream-serde-node': 4.2.5 + '@smithy/fetch-http-handler': 5.3.6 + '@smithy/hash-blob-browser': 4.2.6 + '@smithy/hash-node': 4.2.5 + '@smithy/hash-stream-node': 4.2.5 + '@smithy/invalid-dependency': 4.2.5 + '@smithy/md5-js': 4.2.5 + '@smithy/middleware-content-length': 4.2.5 + '@smithy/middleware-endpoint': 4.3.14 + '@smithy/middleware-retry': 4.4.14 + '@smithy/middleware-serde': 4.2.6 + '@smithy/middleware-stack': 4.2.5 + '@smithy/node-config-provider': 4.3.5 + '@smithy/node-http-handler': 4.4.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/smithy-client': 4.9.10 + '@smithy/types': 4.9.0 + '@smithy/url-parser': 4.2.5 + '@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.13 + '@smithy/util-defaults-mode-node': 4.2.16 + '@smithy/util-endpoints': 3.2.5 + '@smithy/util-middleware': 4.2.5 + '@smithy/util-retry': 4.2.5 + '@smithy/util-stream': 4.5.6 + '@smithy/util-utf8': 4.2.0 + '@smithy/util-waiter': 4.2.5 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/client-sso@3.948.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.947.0 + '@aws-sdk/middleware-host-header': 3.936.0 + '@aws-sdk/middleware-logger': 3.936.0 + '@aws-sdk/middleware-recursion-detection': 3.948.0 + '@aws-sdk/middleware-user-agent': 3.947.0 + '@aws-sdk/region-config-resolver': 3.936.0 + '@aws-sdk/types': 3.936.0 + '@aws-sdk/util-endpoints': 3.936.0 + '@aws-sdk/util-user-agent-browser': 3.936.0 + '@aws-sdk/util-user-agent-node': 3.947.0 + '@smithy/config-resolver': 4.4.3 + '@smithy/core': 3.18.7 + '@smithy/fetch-http-handler': 5.3.6 + '@smithy/hash-node': 4.2.5 + '@smithy/invalid-dependency': 4.2.5 + '@smithy/middleware-content-length': 4.2.5 + '@smithy/middleware-endpoint': 4.3.14 + '@smithy/middleware-retry': 4.4.14 + '@smithy/middleware-serde': 4.2.6 + '@smithy/middleware-stack': 4.2.5 + '@smithy/node-config-provider': 4.3.5 + '@smithy/node-http-handler': 4.4.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/smithy-client': 4.9.10 + '@smithy/types': 4.9.0 + '@smithy/url-parser': 4.2.5 + '@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.13 + '@smithy/util-defaults-mode-node': 4.2.16 + '@smithy/util-endpoints': 3.2.5 + '@smithy/util-middleware': 4.2.5 + '@smithy/util-retry': 4.2.5 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/core@3.947.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@aws-sdk/xml-builder': 3.930.0 + '@smithy/core': 3.18.7 + '@smithy/node-config-provider': 4.3.5 + '@smithy/property-provider': 4.2.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/signature-v4': 5.3.5 + '@smithy/smithy-client': 4.9.10 + '@smithy/types': 4.9.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-middleware': 4.2.5 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-env@3.947.0': + dependencies: + '@aws-sdk/core': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@smithy/property-provider': 4.2.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-http@3.947.0': + dependencies: + '@aws-sdk/core': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@smithy/fetch-http-handler': 5.3.6 + '@smithy/node-http-handler': 4.4.5 + '@smithy/property-provider': 4.2.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/smithy-client': 4.9.10 + '@smithy/types': 4.9.0 + '@smithy/util-stream': 4.5.6 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-ini@3.948.0': + dependencies: + '@aws-sdk/core': 3.947.0 + '@aws-sdk/credential-provider-env': 3.947.0 + '@aws-sdk/credential-provider-http': 3.947.0 + '@aws-sdk/credential-provider-login': 3.948.0 + '@aws-sdk/credential-provider-process': 3.947.0 + '@aws-sdk/credential-provider-sso': 3.948.0 + '@aws-sdk/credential-provider-web-identity': 3.948.0 + '@aws-sdk/nested-clients': 3.948.0 + '@aws-sdk/types': 3.936.0 + '@smithy/credential-provider-imds': 4.2.5 + '@smithy/property-provider': 4.2.5 + '@smithy/shared-ini-file-loader': 4.4.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-login@3.948.0': + dependencies: + '@aws-sdk/core': 3.947.0 + '@aws-sdk/nested-clients': 3.948.0 + '@aws-sdk/types': 3.936.0 + '@smithy/property-provider': 4.2.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/shared-ini-file-loader': 4.4.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-node@3.948.0': + dependencies: + '@aws-sdk/credential-provider-env': 3.947.0 + '@aws-sdk/credential-provider-http': 3.947.0 + '@aws-sdk/credential-provider-ini': 3.948.0 + '@aws-sdk/credential-provider-process': 3.947.0 + '@aws-sdk/credential-provider-sso': 3.948.0 + '@aws-sdk/credential-provider-web-identity': 3.948.0 + '@aws-sdk/types': 3.936.0 + '@smithy/credential-provider-imds': 4.2.5 + '@smithy/property-provider': 4.2.5 + '@smithy/shared-ini-file-loader': 4.4.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-process@3.947.0': + dependencies: + '@aws-sdk/core': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@smithy/property-provider': 4.2.5 + '@smithy/shared-ini-file-loader': 4.4.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-sso@3.948.0': + dependencies: + '@aws-sdk/client-sso': 3.948.0 + '@aws-sdk/core': 3.947.0 + '@aws-sdk/token-providers': 3.948.0 + '@aws-sdk/types': 3.936.0 + '@smithy/property-provider': 4.2.5 + '@smithy/shared-ini-file-loader': 4.4.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-web-identity@3.948.0': + dependencies: + '@aws-sdk/core': 3.947.0 + '@aws-sdk/nested-clients': 3.948.0 + '@aws-sdk/types': 3.936.0 + '@smithy/property-provider': 4.2.5 + '@smithy/shared-ini-file-loader': 4.4.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/lib-storage@3.948.0(@aws-sdk/client-s3@3.948.0)': + dependencies: + '@aws-sdk/client-s3': 3.948.0 + '@smithy/abort-controller': 4.2.5 + '@smithy/middleware-endpoint': 4.3.14 + '@smithy/smithy-client': 4.9.10 + buffer: 5.6.0 + events: 3.3.0 + stream-browserify: 3.0.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-bucket-endpoint@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@aws-sdk/util-arn-parser': 3.893.0 + '@smithy/node-config-provider': 4.3.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + '@smithy/util-config-provider': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-expect-continue@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-flexible-checksums@3.947.0': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@aws-crypto/crc32c': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/core': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@smithy/is-array-buffer': 4.2.0 + '@smithy/node-config-provider': 4.3.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + '@smithy/util-middleware': 4.2.5 + '@smithy/util-stream': 4.5.6 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-host-header@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-location-constraint@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-logger@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-recursion-detection@3.948.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@aws/lambda-invoke-store': 0.2.2 + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-sdk-s3@3.947.0': + dependencies: + '@aws-sdk/core': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@aws-sdk/util-arn-parser': 3.893.0 + '@smithy/core': 3.18.7 + '@smithy/node-config-provider': 4.3.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/signature-v4': 5.3.5 + '@smithy/smithy-client': 4.9.10 + '@smithy/types': 4.9.0 + '@smithy/util-config-provider': 4.2.0 + '@smithy/util-middleware': 4.2.5 + '@smithy/util-stream': 4.5.6 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-ssec@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-user-agent@3.947.0': + dependencies: + '@aws-sdk/core': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@aws-sdk/util-endpoints': 3.936.0 + '@smithy/core': 3.18.7 + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/nested-clients@3.948.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.947.0 + '@aws-sdk/middleware-host-header': 3.936.0 + '@aws-sdk/middleware-logger': 3.936.0 + '@aws-sdk/middleware-recursion-detection': 3.948.0 + '@aws-sdk/middleware-user-agent': 3.947.0 + '@aws-sdk/region-config-resolver': 3.936.0 + '@aws-sdk/types': 3.936.0 + '@aws-sdk/util-endpoints': 3.936.0 + '@aws-sdk/util-user-agent-browser': 3.936.0 + '@aws-sdk/util-user-agent-node': 3.947.0 + '@smithy/config-resolver': 4.4.3 + '@smithy/core': 3.18.7 + '@smithy/fetch-http-handler': 5.3.6 + '@smithy/hash-node': 4.2.5 + '@smithy/invalid-dependency': 4.2.5 + '@smithy/middleware-content-length': 4.2.5 + '@smithy/middleware-endpoint': 4.3.14 + '@smithy/middleware-retry': 4.4.14 + '@smithy/middleware-serde': 4.2.6 + '@smithy/middleware-stack': 4.2.5 + '@smithy/node-config-provider': 4.3.5 + '@smithy/node-http-handler': 4.4.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/smithy-client': 4.9.10 + '@smithy/types': 4.9.0 + '@smithy/url-parser': 4.2.5 + '@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.13 + '@smithy/util-defaults-mode-node': 4.2.16 + '@smithy/util-endpoints': 3.2.5 + '@smithy/util-middleware': 4.2.5 + '@smithy/util-retry': 4.2.5 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/region-config-resolver@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@smithy/config-resolver': 4.4.3 + '@smithy/node-config-provider': 4.3.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/s3-request-presigner@3.952.0': + dependencies: + '@aws-sdk/signature-v4-multi-region': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@aws-sdk/util-format-url': 3.936.0 + '@smithy/middleware-endpoint': 4.3.14 + '@smithy/protocol-http': 5.3.5 + '@smithy/smithy-client': 4.9.10 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/signature-v4-multi-region@3.947.0': + dependencies: + '@aws-sdk/middleware-sdk-s3': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@smithy/protocol-http': 5.3.5 + '@smithy/signature-v4': 5.3.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/token-providers@3.948.0': + dependencies: + '@aws-sdk/core': 3.947.0 + '@aws-sdk/nested-clients': 3.948.0 + '@aws-sdk/types': 3.936.0 + '@smithy/property-provider': 4.2.5 + '@smithy/shared-ini-file-loader': 4.4.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/types@3.936.0': + dependencies: + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/util-arn-parser@3.893.0': + dependencies: + tslib: 2.8.1 + + '@aws-sdk/util-endpoints@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@smithy/types': 4.9.0 + '@smithy/url-parser': 4.2.5 + '@smithy/util-endpoints': 3.2.5 + tslib: 2.8.1 + + '@aws-sdk/util-format-url@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@smithy/querystring-builder': 4.2.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/util-locate-window@3.893.0': + dependencies: + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-browser@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@smithy/types': 4.9.0 + bowser: 2.13.1 + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-node@3.947.0': + dependencies: + '@aws-sdk/middleware-user-agent': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@smithy/node-config-provider': 4.3.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/xml-builder@3.930.0': + dependencies: + '@smithy/types': 4.9.0 + fast-xml-parser: 5.2.5 + tslib: 2.8.1 + + '@aws/lambda-invoke-store@0.2.2': {} + '@babel/code-frame@7.26.2': dependencies: '@babel/helper-validator-identifier': 7.25.9 @@ -11588,7 +13140,7 @@ snapshots: '@babel/traverse': 7.26.10 '@babel/types': 7.26.10 convert-source-map: 2.0.0 - debug: 4.4.1 + debug: 4.4.3 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -11603,6 +13155,14 @@ snapshots: '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.1.0 + '@babel/generator@7.28.5': + dependencies: + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + '@babel/helper-annotate-as-pure@7.25.9': dependencies: '@babel/types': 7.26.10 @@ -11708,6 +13268,8 @@ snapshots: '@babel/helper-validator-identifier@7.27.1': {} + '@babel/helper-validator-identifier@7.28.5': {} + '@babel/helper-validator-option@7.25.9': {} '@babel/helper-wrap-function@7.25.9': @@ -11731,6 +13293,10 @@ snapshots: dependencies: '@babel/types': 7.28.4 + '@babel/parser@7.28.5': + dependencies: + '@babel/types': 7.28.5 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -12367,6 +13933,11 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 + '@babel/types@7.28.5': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + '@bany/curl-to-json@1.2.8': dependencies: minimist: 1.2.8 @@ -12686,6 +14257,12 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/core@1.7.1': + dependencies: + '@emnapi/wasi-threads': 1.1.0 + tslib: 2.8.1 + optional: true + '@emnapi/runtime@1.3.1': dependencies: tslib: 2.8.1 @@ -12701,6 +14278,11 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/wasi-threads@1.1.0': + dependencies: + tslib: 2.8.1 + optional: true + '@emotion/babel-plugin@11.13.5': dependencies: '@babel/helper-module-imports': 7.25.9 @@ -13046,7 +14628,7 @@ snapshots: '@eslint/js@8.57.1': {} - '@fastgpt-sdk/plugin@0.2.16(@types/node@20.14.0)': + '@fastgpt-sdk/plugin@0.2.17(@types/node@20.14.0)': dependencies: '@fortaine/fetch-event-source': 3.0.6 '@ts-rest/core': 3.52.1(@types/node@20.14.0)(zod@3.25.76) @@ -13485,6 +15067,11 @@ snapshots: '@types/yargs': 17.0.33 chalk: 4.1.2 + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/gen-mapping@0.3.8': dependencies: '@jridgewell/set-array': 1.2.1 @@ -13509,6 +15096,11 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping@0.3.9': dependencies: '@jridgewell/resolve-uri': 3.1.2 @@ -13829,6 +15421,13 @@ snapshots: '@tybys/wasm-util': 0.9.0 optional: true + '@napi-rs/wasm-runtime@1.1.0': + dependencies: + '@emnapi/core': 1.7.1 + '@emnapi/runtime': 1.7.1 + '@tybys/wasm-util': 0.10.1 + optional: true + '@nestjs/cli@10.4.9': dependencies: '@angular-devkit/core': 17.3.11(chokidar@3.6.0) @@ -14259,6 +15858,8 @@ snapshots: '@opentelemetry/api-logs': 0.203.0 winston-transport: 4.9.0 + '@oxc-project/types@0.101.0': {} + '@oxc-resolver/binding-darwin-arm64@5.0.0': optional: true @@ -14401,6 +16002,10 @@ snapshots: '@protobufjs/utf8@1.1.0': {} + '@quansync/fs@1.0.0': + dependencies: + quansync: 1.0.0 + '@reactflow/background@11.3.14(@types/react@18.3.1)(immer@9.0.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@reactflow/core': 11.11.4(@types/react@18.3.1)(immer@9.0.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -14485,6 +16090,49 @@ snapshots: '@codemirror/state': 6.5.2 '@codemirror/view': 6.38.6 + '@rolldown/binding-android-arm64@1.0.0-beta.53': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.0-beta.53': + optional: true + + '@rolldown/binding-darwin-x64@1.0.0-beta.53': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.0-beta.53': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.53': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.53': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.53': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.53': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.0-beta.53': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.0-beta.53': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.0-beta.53': + dependencies: + '@napi-rs/wasm-runtime': 1.1.0 + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.53': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.53': + optional: true + + '@rolldown/pluginutils@1.0.0-beta.53': {} + '@rollup/rollup-android-arm-eabi@4.35.0': optional: true @@ -14902,6 +16550,344 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 + '@smithy/abort-controller@4.2.5': + dependencies: + '@smithy/types': 4.9.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.3': + dependencies: + '@smithy/node-config-provider': 4.3.5 + '@smithy/types': 4.9.0 + '@smithy/util-config-provider': 4.2.0 + '@smithy/util-endpoints': 3.2.5 + '@smithy/util-middleware': 4.2.5 + tslib: 2.8.1 + + '@smithy/core@3.18.7': + dependencies: + '@smithy/middleware-serde': 4.2.6 + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-middleware': 4.2.5 + '@smithy/util-stream': 4.5.6 + '@smithy/util-utf8': 4.2.0 + '@smithy/uuid': 1.1.0 + tslib: 2.8.1 + + '@smithy/credential-provider-imds@4.2.5': + dependencies: + '@smithy/node-config-provider': 4.3.5 + '@smithy/property-provider': 4.2.5 + '@smithy/types': 4.9.0 + '@smithy/url-parser': 4.2.5 + tslib: 2.8.1 + + '@smithy/eventstream-codec@4.2.5': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@smithy/types': 4.9.0 + '@smithy/util-hex-encoding': 4.2.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-browser@4.2.5': + dependencies: + '@smithy/eventstream-serde-universal': 4.2.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-config-resolver@4.3.5': + dependencies: + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-node@4.2.5': + dependencies: + '@smithy/eventstream-serde-universal': 4.2.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-universal@4.2.5': + dependencies: + '@smithy/eventstream-codec': 4.2.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/fetch-http-handler@5.3.6': + dependencies: + '@smithy/protocol-http': 5.3.5 + '@smithy/querystring-builder': 4.2.5 + '@smithy/types': 4.9.0 + '@smithy/util-base64': 4.3.0 + tslib: 2.8.1 + + '@smithy/hash-blob-browser@4.2.6': + dependencies: + '@smithy/chunked-blob-reader': 5.2.0 + '@smithy/chunked-blob-reader-native': 4.2.1 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/hash-node@4.2.5': + dependencies: + '@smithy/types': 4.9.0 + '@smithy/util-buffer-from': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/hash-stream-node@4.2.5': + dependencies: + '@smithy/types': 4.9.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/invalid-dependency@4.2.5': + dependencies: + '@smithy/types': 4.9.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.5': + dependencies: + '@smithy/types': 4.9.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/middleware-content-length@4.2.5': + dependencies: + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/middleware-endpoint@4.3.14': + dependencies: + '@smithy/core': 3.18.7 + '@smithy/middleware-serde': 4.2.6 + '@smithy/node-config-provider': 4.3.5 + '@smithy/shared-ini-file-loader': 4.4.0 + '@smithy/types': 4.9.0 + '@smithy/url-parser': 4.2.5 + '@smithy/util-middleware': 4.2.5 + tslib: 2.8.1 + + '@smithy/middleware-retry@4.4.14': + dependencies: + '@smithy/node-config-provider': 4.3.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/service-error-classification': 4.2.5 + '@smithy/smithy-client': 4.9.10 + '@smithy/types': 4.9.0 + '@smithy/util-middleware': 4.2.5 + '@smithy/util-retry': 4.2.5 + '@smithy/uuid': 1.1.0 + tslib: 2.8.1 + + '@smithy/middleware-serde@4.2.6': + dependencies: + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/middleware-stack@4.2.5': + dependencies: + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/node-config-provider@4.3.5': + dependencies: + '@smithy/property-provider': 4.2.5 + '@smithy/shared-ini-file-loader': 4.4.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/node-http-handler@4.4.5': + dependencies: + '@smithy/abort-controller': 4.2.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/querystring-builder': 4.2.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/property-provider@4.2.5': + dependencies: + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/protocol-http@5.3.5': + dependencies: + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/querystring-builder@4.2.5': + dependencies: + '@smithy/types': 4.9.0 + '@smithy/util-uri-escape': 4.2.0 + tslib: 2.8.1 + + '@smithy/querystring-parser@4.2.5': + dependencies: + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/service-error-classification@4.2.5': + dependencies: + '@smithy/types': 4.9.0 + + '@smithy/shared-ini-file-loader@4.4.0': + dependencies: + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/signature-v4@5.3.5': + dependencies: + '@smithy/is-array-buffer': 4.2.0 + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + '@smithy/util-hex-encoding': 4.2.0 + '@smithy/util-middleware': 4.2.5 + '@smithy/util-uri-escape': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/smithy-client@4.9.10': + dependencies: + '@smithy/core': 3.18.7 + '@smithy/middleware-endpoint': 4.3.14 + '@smithy/middleware-stack': 4.2.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + '@smithy/util-stream': 4.5.6 + tslib: 2.8.1 + + '@smithy/types@4.9.0': + dependencies: + tslib: 2.8.1 + + '@smithy/url-parser@4.2.5': + dependencies: + '@smithy/querystring-parser': 4.2.5 + '@smithy/types': 4.9.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.13': + dependencies: + '@smithy/property-provider': 4.2.5 + '@smithy/smithy-client': 4.9.10 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/util-defaults-mode-node@4.2.16': + dependencies: + '@smithy/config-resolver': 4.4.3 + '@smithy/credential-provider-imds': 4.2.5 + '@smithy/node-config-provider': 4.3.5 + '@smithy/property-provider': 4.2.5 + '@smithy/smithy-client': 4.9.10 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/util-endpoints@3.2.5': + dependencies: + '@smithy/node-config-provider': 4.3.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/util-hex-encoding@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-middleware@4.2.5': + dependencies: + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/util-retry@4.2.5': + dependencies: + '@smithy/service-error-classification': 4.2.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/util-stream@4.5.6': + dependencies: + '@smithy/fetch-http-handler': 5.3.6 + '@smithy/node-http-handler': 4.4.5 + '@smithy/types': 4.9.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.5': + dependencies: + '@smithy/abort-controller': 4.2.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/uuid@1.1.0': + dependencies: + tslib: 2.8.1 + '@svgr/babel-plugin-add-jsx-attribute@6.5.1(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -15025,6 +17011,8 @@ snapshots: '@tokenizer/token@0.3.0': {} + '@tootallnate/quickjs-emscripten@0.23.0': {} + '@trysound/sax@0.2.0': {} '@ts-rest/core@3.52.1(@types/node@20.14.0)(zod@3.25.76)': @@ -15040,11 +17028,18 @@ snapshots: '@tsconfig/node16@1.0.4': {} + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 + optional: true + '@tybys/wasm-util@0.9.0': dependencies: tslib: 2.8.1 optional: true + '@types/ali-oss@6.16.13': {} + '@types/async-retry@1.4.9': dependencies: '@types/retry': 0.12.5 @@ -15677,14 +17672,6 @@ snapshots: chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.1.1(vite@6.2.2(@types/node@20.17.24)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.8.1))': - dependencies: - '@vitest/spy': 3.1.1 - estree-walker: 3.0.3 - magic-string: 0.30.17 - optionalDependencies: - vite: 6.2.2(@types/node@20.17.24)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.8.1) - '@vitest/mocker@3.1.1(vite@6.2.2(@types/node@24.0.13)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.8.1))': dependencies: '@vitest/spy': 3.1.1 @@ -16033,8 +18020,14 @@ snapshots: acorn@8.15.0: {} + address@1.2.2: {} + agent-base@7.1.3: {} + agentkeepalive@3.5.3: + dependencies: + humanize-ms: 1.2.1 + agentkeepalive@4.6.0: dependencies: humanize-ms: 1.2.1 @@ -16063,6 +18056,10 @@ snapshots: optionalDependencies: ajv: 8.17.1 + ajv-formats@1.6.1(ajv@7.2.4): + optionalDependencies: + ajv: 7.2.4 + ajv-formats@2.1.1(ajv@8.12.0): optionalDependencies: ajv: 8.12.0 @@ -16091,6 +18088,13 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ajv@7.2.4: + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + ajv@8.12.0: dependencies: fast-deep-equal: 3.1.3 @@ -16105,6 +18109,37 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 + ali-oss@6.23.0: + dependencies: + address: 1.2.2 + agentkeepalive: 3.5.3 + bowser: 1.9.4 + copy-to: 2.0.1 + dateformat: 2.2.0 + debug: 4.4.3 + destroy: 1.2.0 + end-or-error: 1.0.1 + get-ready: 1.0.0 + humanize-ms: 1.2.1 + is-type-of: 1.4.0 + js-base64: 2.6.4 + jstoxml: 2.2.9 + lodash: 4.17.21 + merge-descriptors: 1.0.3 + mime: 2.6.0 + platform: 1.3.6 + pump: 3.0.2 + qs: 6.14.0 + sdk-base: 2.0.1 + stream-http: 2.8.2 + stream-wormhole: 1.1.0 + urllib: 2.44.0 + utility: 1.18.0 + xml2js: 0.6.2 + transitivePeerDependencies: + - proxy-agent + - supports-color + ansi-align@3.0.1: dependencies: string-width: 4.2.3 @@ -16135,6 +18170,8 @@ snapshots: ansi-styles@6.2.1: {} + ansis@4.2.0: {} + any-promise@1.3.0: {} anymatch@3.1.3: @@ -16233,12 +18270,27 @@ snapshots: asap@2.0.6: {} + asn1@0.2.6: + dependencies: + safer-buffer: 2.1.2 + + assert-plus@1.0.0: {} + assertion-error@1.1.0: {} assertion-error@2.0.1: {} + ast-kit@2.2.0: + dependencies: + '@babel/parser': 7.28.5 + pathe: 2.0.3 + ast-types-flow@0.0.8: {} + ast-types@0.13.4: + dependencies: + tslib: 2.8.1 + async-function@1.0.0: {} async-mutex@0.5.0: @@ -16251,6 +18303,8 @@ snapshots: atomic-sleep@1.0.0: {} + atomically@1.7.0: {} + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.1.0 @@ -16260,8 +18314,12 @@ snapshots: '@fastify/error': 3.4.1 fastq: 1.19.1 + aws-sign2@0.7.0: {} + aws-ssl-profiles@1.1.2: {} + aws4@1.13.2: {} + axe-core@4.10.3: {} axios@1.12.1: @@ -16372,8 +18430,16 @@ snapshots: base64-js@1.5.1: {} + basic-ftp@5.0.5: {} + + bcrypt-pbkdf@1.0.2: + dependencies: + tweetnacl: 0.14.5 + binary-extensions@2.3.0: {} + birpc@3.0.0: {} + bl@1.2.3: dependencies: readable-stream: 2.3.8 @@ -16430,6 +18496,10 @@ snapshots: boolbase@1.0.0: {} + bowser@1.9.4: {} + + bowser@2.13.1: {} + boxen@7.1.1: dependencies: ansi-align: 3.0.1 @@ -16490,6 +18560,11 @@ snapshots: buffer-from@1.1.2: {} + buffer@5.6.0: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + buffer@5.7.1: dependencies: base64-js: 1.5.1 @@ -16500,6 +18575,8 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 + builtin-status-codes@3.0.0: {} + bullmq@5.52.2: dependencies: cron-parser: 4.9.0 @@ -16587,6 +18664,8 @@ snapshots: caniuse-lite@1.0.30001757: {} + caseless@0.12.0: {} + ccount@2.0.1: {} chai@4.5.0: @@ -16849,6 +18928,20 @@ snapshots: readable-stream: 3.6.2 typedarray: 0.0.6 + conf@9.0.2: + dependencies: + ajv: 7.2.4 + ajv-formats: 1.6.1(ajv@7.2.4) + atomically: 1.7.0 + debounce-fn: 4.0.0 + dot-prop: 6.0.1 + env-paths: 2.2.1 + json-schema-typed: 7.0.3 + make-dir: 3.1.0 + onetime: 5.1.2 + pkg-up: 3.1.0 + semver: 7.7.3 + confbox@0.1.8: {} config-chain@1.1.13: @@ -16892,12 +18985,16 @@ snapshots: dependencies: toggle-selection: 1.0.6 + copy-to@2.0.1: {} + core-js-compat@3.41.0: dependencies: browserslist: 4.24.4 core-js@3.41.0: {} + core-util-is@1.0.2: {} + core-util-is@1.0.3: {} cors@2.8.5: @@ -16905,6 +19002,13 @@ snapshots: object-assign: 4.1.1 vary: 1.1.2 + cos-nodejs-sdk-v5@2.15.4: + dependencies: + conf: 9.0.2 + fast-xml-parser: 4.2.5 + mime-types: 2.1.35 + request: 2.88.2 + cose-base@1.0.3: dependencies: layout-base: 1.0.2 @@ -17181,6 +19285,12 @@ snapshots: damerau-levenshtein@1.0.8: {} + dashdash@1.14.1: + dependencies: + assert-plus: 1.0.0 + + data-uri-to-buffer@6.0.2: {} + data-view-buffer@1.0.2: dependencies: call-bound: 1.0.4 @@ -17203,8 +19313,14 @@ snapshots: dependencies: '@babel/runtime': 7.26.10 + dateformat@2.2.0: {} + dayjs@1.11.13: {} + debounce-fn@4.0.0: + dependencies: + mimic-fn: 3.1.0 + debounce@1.2.1: {} debug@2.6.9: @@ -17299,6 +19415,10 @@ snapshots: deepmerge@4.3.1: {} + default-user-agent@1.0.0: + dependencies: + os-name: 1.0.3 + defaults@1.0.4: dependencies: clone: 1.0.4 @@ -17319,6 +19439,12 @@ snapshots: defu@6.1.4: {} + degenerator@5.0.1: + dependencies: + ast-types: 0.13.4 + escodegen: 2.1.0 + esprima: 4.0.1 + delaunator@5.0.1: dependencies: robust-predicates: 3.0.2 @@ -17362,6 +19488,8 @@ snapshots: diff@5.2.0: {} + digest-header@1.1.0: {} + dijkstrajs@1.0.3: {} dingbat-to-unicode@1.0.1: {} @@ -17431,6 +19559,8 @@ snapshots: dotenv@16.5.0: {} + dts-resolver@2.1.3: {} + duck@0.1.12: dependencies: underscore: 1.13.7 @@ -17445,6 +19575,11 @@ snapshots: eastasianwidth@0.2.0: {} + ecc-jsbn@0.1.2: + dependencies: + jsbn: 0.1.1 + safer-buffer: 2.1.2 + ecdsa-sig-formatter@1.0.11: dependencies: safe-buffer: 5.2.1 @@ -17478,6 +19613,8 @@ snapshots: emoji-regex@9.2.2: {} + empathic@2.0.0: {} + enabled@2.0.0: {} encodeurl@1.0.2: {} @@ -17492,6 +19629,8 @@ snapshots: dependencies: once: 1.4.0 + end-or-error@1.0.1: {} + enhanced-resolve@5.18.1: dependencies: graceful-fs: 4.2.11 @@ -17609,6 +19748,8 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 + es-toolkit@1.43.0: {} + esbuild@0.21.5: optionalDependencies: '@esbuild/aix-ppc64': 0.21.5 @@ -17706,6 +19847,14 @@ snapshots: escape-string-regexp@5.0.0: {} + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + eslint-config-next@14.2.26(eslint@8.56.0)(typescript@5.8.2): dependencies: '@next/eslint-plugin-next': 14.2.26 @@ -17714,7 +19863,7 @@ snapshots: '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.8.2) eslint: 8.56.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.9.0(eslint-plugin-import@2.31.0)(eslint@8.56.0) + eslint-import-resolver-typescript: 3.9.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1))(eslint@8.56.0) eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.2))(eslint-import-resolver-typescript@3.9.0)(eslint@8.56.0) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.56.0) eslint-plugin-react: 7.37.4(eslint@8.56.0) @@ -17754,8 +19903,8 @@ snapshots: '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.8.2) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.9.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1))(eslint@8.57.1) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-typescript@3.9.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-import-resolver-typescript: 3.9.0(eslint-plugin-import@2.31.0)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-typescript@3.9.0)(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1) eslint-plugin-react: 7.37.4(eslint@8.57.1) eslint-plugin-react-hooks: 5.0.0-canary-7118f5dd7-20230705(eslint@8.57.1) @@ -17774,22 +19923,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.9.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1))(eslint@8.57.1): - dependencies: - '@nolyfill/is-core-module': 1.0.39 - debug: 4.4.0 - eslint: 8.57.1 - get-tsconfig: 4.10.0 - is-bun-module: 1.3.0 - oxc-resolver: 5.0.0 - stable-hash: 0.0.5 - tinyglobby: 0.2.12 - optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-typescript@3.9.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) - transitivePeerDependencies: - - supports-color - - eslint-import-resolver-typescript@3.9.0(eslint-plugin-import@2.31.0)(eslint@8.56.0): + eslint-import-resolver-typescript@3.9.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1))(eslint@8.56.0): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.0 @@ -17800,7 +19934,7 @@ snapshots: stable-hash: 0.0.5 tinyglobby: 0.2.12 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.2))(eslint-import-resolver-typescript@3.9.0)(eslint@8.56.0) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-typescript@3.9.0)(eslint@8.57.1) transitivePeerDependencies: - supports-color @@ -17819,25 +19953,14 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0)(eslint@8.56.0): + eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1))(eslint@8.56.0))(eslint@8.56.0): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.8.2) eslint: 8.56.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.9.0(eslint-plugin-import@2.31.0)(eslint@8.56.0) - transitivePeerDependencies: - - supports-color - - eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): - dependencies: - debug: 3.2.7 - optionalDependencies: - '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.8.2) - eslint: 8.57.1 - eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.9.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1))(eslint@8.57.1) + eslint-import-resolver-typescript: 3.9.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1))(eslint@8.56.0) transitivePeerDependencies: - supports-color @@ -17863,7 +19986,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.56.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0)(eslint@8.56.0) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1))(eslint@8.56.0))(eslint@8.56.0) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -17881,35 +20004,6 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-typescript@3.9.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): - dependencies: - '@rtsao/scc': 1.1.0 - array-includes: 3.1.8 - array.prototype.findlastindex: 1.2.6 - array.prototype.flat: 1.3.3 - array.prototype.flatmap: 1.3.3 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.57.1 - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) - hasown: 2.0.2 - is-core-module: 2.16.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.fromentries: 2.0.8 - object.groupby: 1.0.3 - object.values: 1.2.1 - semver: 6.3.1 - string.prototype.trimend: 1.0.9 - tsconfig-paths: 3.15.0 - optionalDependencies: - '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.8.2) - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-typescript@3.9.0)(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 @@ -18298,6 +20392,10 @@ snapshots: transitivePeerDependencies: - supports-color + extend-shallow@2.0.1: + dependencies: + is-extendable: 0.1.1 + extend@3.0.2: {} external-editor@3.1.0: @@ -18306,6 +20404,8 @@ snapshots: iconv-lite: 0.4.24 tmp: 0.0.33 + extsprintf@1.3.0: {} + fast-content-type-parse@1.1.0: {} fast-decode-uri-component@1.0.1: {} @@ -18350,10 +20450,18 @@ snapshots: fast-uri@3.0.6: {} + fast-xml-parser@4.2.5: + dependencies: + strnum: 1.1.2 + fast-xml-parser@4.5.3: dependencies: strnum: 1.1.2 + fast-xml-parser@5.2.5: + dependencies: + strnum: 2.1.2 + fastify-plugin@4.5.1: {} fastify@4.28.1: @@ -18414,6 +20522,10 @@ snapshots: optionalDependencies: picomatch: 4.0.2 + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + fecha@4.2.3: {} figures@3.2.0: @@ -18484,6 +20596,10 @@ snapshots: find-root@1.1.0: {} + find-up@3.0.0: + dependencies: + locate-path: 3.0.0 + find-up@4.1.0: dependencies: locate-path: 5.0.0 @@ -18525,6 +20641,8 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 + forever-agent@0.6.1: {} + fork-ts-checker-webpack-plugin@9.0.2(typescript@5.7.2)(webpack@5.97.1): dependencies: '@babel/code-frame': 7.26.2 @@ -18537,7 +20655,7 @@ snapshots: minimatch: 3.1.2 node-abort-controller: 3.1.1 schema-utils: 3.3.0 - semver: 7.7.2 + semver: 7.7.3 tapable: 2.2.1 typescript: 5.7.2 webpack: 5.97.1 @@ -18546,6 +20664,12 @@ snapshots: form-data-encoder@2.1.4: {} + form-data@2.3.3: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + form-data@4.0.4: dependencies: asynckit: 0.4.0 @@ -18568,6 +20692,13 @@ snapshots: once: 1.4.0 qs: 6.14.0 + formstream@1.5.2: + dependencies: + destroy: 1.2.0 + mime: 2.6.0 + node-hex: 1.0.1 + pause-stream: 0.0.11 + forwarded@0.2.0: {} framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1): @@ -18660,6 +20791,8 @@ snapshots: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 + get-ready@1.0.0: {} + get-stream@2.3.1: dependencies: object-assign: 4.1.1 @@ -18684,6 +20817,22 @@ snapshots: dependencies: resolve-pkg-maps: 1.0.0 + get-tsconfig@4.13.0: + dependencies: + resolve-pkg-maps: 1.0.0 + + get-uri@6.0.5: + dependencies: + basic-ftp: 5.0.5 + data-uri-to-buffer: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + getpass@0.1.7: + dependencies: + assert-plus: 1.0.0 + github-from-package@0.0.0: {} github-slugger@2.0.0: {} @@ -18774,6 +20923,13 @@ snapshots: dependencies: duplexer: 0.1.2 + har-schema@2.0.0: {} + + har-validator@5.1.5: + dependencies: + ajv: 6.12.6 + har-schema: 2.0.0 + has-bigints@1.1.0: {} has-flag@3.0.0: {} @@ -19033,10 +21189,16 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.3 - debug: 4.4.1 + debug: 4.4.3 transitivePeerDependencies: - supports-color + http-signature@1.2.0: + dependencies: + assert-plus: 1.0.0 + jsprim: 1.4.2 + sshpk: 1.18.0 + http2-wrapper@2.2.1: dependencies: quick-lru: 5.1.1 @@ -19045,7 +21207,7 @@ snapshots: https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.3 - debug: 4.4.1 + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -19110,6 +21272,8 @@ snapshots: pkg-dir: 4.2.0 resolve-cwd: 3.0.0 + import-without-cache@0.2.3: {} + imurmurhash@0.1.4: {} indent-string@4.0.0: {} @@ -19264,6 +21428,8 @@ snapshots: dependencies: ci-info: 3.9.0 + is-class-hotfix@0.0.6: {} + is-core-module@2.16.1: dependencies: hasown: 2.0.2 @@ -19283,6 +21449,8 @@ snapshots: is-decimal@2.0.1: {} + is-extendable@0.1.1: {} + is-extglob@2.1.1: {} is-finalizationregistry@1.1.1: @@ -19384,6 +21552,12 @@ snapshots: has-symbols: 1.1.0 safe-regex-test: 1.1.0 + is-type-of@1.4.0: + dependencies: + core-util-is: 1.0.3 + is-class-hotfix: 0.0.6 + isstream: 0.1.2 + is-typed-array@1.1.15: dependencies: which-typed-array: 1.1.19 @@ -19425,6 +21599,8 @@ snapshots: isomorphic.js@0.2.5: {} + isstream@0.1.2: {} + istanbul-lib-coverage@3.2.2: {} istanbul-lib-instrument@5.2.1: @@ -19440,10 +21616,10 @@ snapshots: istanbul-lib-instrument@6.0.3: dependencies: '@babel/core': 7.26.10 - '@babel/parser': 7.26.10 + '@babel/parser': 7.28.4 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 - semver: 7.7.2 + semver: 7.7.3 transitivePeerDependencies: - supports-color @@ -19761,7 +21937,7 @@ snapshots: jest-util: 29.7.0 natural-compare: 1.4.0 pretty-format: 29.7.0 - semver: 7.7.2 + semver: 7.7.3 transitivePeerDependencies: - supports-color @@ -19828,6 +22004,8 @@ snapshots: jose@6.1.3: {} + js-base64@2.6.4: {} + js-base64@3.7.8: {} js-cookie@3.0.5: {} @@ -19849,6 +22027,8 @@ snapshots: dependencies: argparse: 2.0.1 + jsbn@0.1.1: {} + jsbn@1.1.0: {} jschardet@3.1.1: {} @@ -19871,10 +22051,16 @@ snapshots: json-schema-traverse@1.0.0: {} + json-schema-typed@7.0.3: {} + + json-schema@0.4.0: {} + json-stable-stringify-without-jsonify@1.0.1: {} json-stringify-deterministic@1.0.12: {} + json-stringify-safe@5.0.1: {} + json5@1.0.2: dependencies: minimist: 1.2.8 @@ -19916,6 +22102,15 @@ snapshots: ms: 2.1.3 semver: 7.7.1 + jsprim@1.4.2: + dependencies: + assert-plus: 1.0.0 + extsprintf: 1.3.0 + json-schema: 0.4.0 + verror: 1.10.0 + + jstoxml@2.2.9: {} + jsx-ast-utils@3.3.5: dependencies: array-includes: 3.1.8 @@ -19970,9 +22165,9 @@ snapshots: langbase@1.1.44(encoding@0.1.13)(react@19.1.1): dependencies: dotenv: 16.4.7 - openai: 4.87.3(encoding@0.1.13)(zod@3.25.51) - zod: 3.25.51 - zod-validation-error: 3.4.0(zod@3.25.51) + openai: 4.87.3(encoding@0.1.13)(zod@3.25.76) + zod: 3.25.76 + zod-validation-error: 3.4.0(zod@3.25.76) optionalDependencies: react: 19.1.1 transitivePeerDependencies: @@ -20106,6 +22301,11 @@ snapshots: mlly: 1.7.4 pkg-types: 1.3.1 + locate-path@3.0.0: + dependencies: + p-locate: 3.0.0 + path-exists: 3.0.0 + locate-path@5.0.0: dependencies: p-locate: 4.1.0 @@ -20228,6 +22428,10 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + magic-string@0.30.8: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -20901,8 +23105,12 @@ snapshots: mime@3.0.0: {} + mime@4.1.0: {} + mimic-fn@2.1.0: {} + mimic-fn@3.1.0: {} + mimic-fn@4.0.0: {} mimic-response@3.1.0: {} @@ -21080,7 +23288,7 @@ snapshots: mquery@5.0.0: dependencies: - debug: 4.4.0 + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -21164,6 +23372,8 @@ snapshots: neo-async@2.6.2: {} + netmask@2.0.2: {} + new-find-package-json@2.0.0: dependencies: debug: 4.4.3 @@ -21407,6 +23617,8 @@ snapshots: transitivePeerDependencies: - supports-color + node-hex@1.0.1: {} + node-int64@0.4.0: {} node-releases@2.0.19: {} @@ -21439,6 +23651,8 @@ snapshots: dependencies: boolbase: 1.0.0 + oauth-sign@0.9.0: {} + object-assign@4.1.1: {} object-hash@3.0.0: {} @@ -21487,6 +23701,8 @@ snapshots: obuf@1.1.2: {} + obug@2.1.1: {} + on-exit-leak-free@2.1.2: {} on-finished@2.4.1: @@ -21525,7 +23741,7 @@ snapshots: transitivePeerDependencies: - encoding - openai@4.87.3(encoding@0.1.13)(zod@3.25.51): + openai@4.87.3(encoding@0.1.13)(zod@3.25.76): dependencies: '@types/node': 18.19.80 '@types/node-fetch': 2.6.12 @@ -21535,7 +23751,7 @@ snapshots: formdata-node: 4.4.1 node-fetch: 2.7.0(encoding@0.1.13) optionalDependencies: - zod: 3.25.51 + zod: 3.25.76 transitivePeerDependencies: - encoding @@ -21578,8 +23794,17 @@ snapshots: string-width: 6.1.0 strip-ansi: 7.1.0 + os-name@1.0.3: + dependencies: + osx-release: 1.1.0 + win-release: 1.1.1 + os-tmpdir@1.0.2: {} + osx-release@1.1.0: + dependencies: + minimist: 1.2.8 + otlp-logger@1.1.10(@opentelemetry/api@1.9.0): dependencies: '@opentelemetry/api-logs': 0.202.0 @@ -21629,6 +23854,10 @@ snapshots: dependencies: yocto-queue: 1.2.1 + p-locate@3.0.0: + dependencies: + p-limit: 2.3.0 + p-locate@4.1.0: dependencies: p-limit: 2.3.0 @@ -21643,6 +23872,24 @@ snapshots: p-try@2.2.0: {} + pac-proxy-agent@7.2.0: + dependencies: + '@tootallnate/quickjs-emscripten': 0.23.0 + agent-base: 7.1.3 + debug: 4.4.3 + get-uri: 6.0.5 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + pac-resolver: 7.0.1 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + + pac-resolver@7.0.1: + dependencies: + degenerator: 5.0.1 + netmask: 2.0.2 + package-json-from-dist@1.0.1: {} package-json@8.1.1: @@ -21650,7 +23897,7 @@ snapshots: got: 12.6.1 registry-auth-token: 5.1.0 registry-url: 6.0.1 - semver: 7.7.2 + semver: 7.7.3 packrup@0.1.2: {} @@ -21710,6 +23957,8 @@ snapshots: parseurl@1.3.3: {} + path-exists@3.0.0: {} + path-exists@4.0.0: {} path-is-absolute@1.0.1: {} @@ -21743,6 +23992,10 @@ snapshots: pathval@2.0.0: {} + pause-stream@0.0.11: + dependencies: + through: 2.3.8 + pdfjs-dist@4.10.38: optionalDependencies: '@napi-rs/canvas': 0.1.69 @@ -21751,6 +24004,8 @@ snapshots: pend@1.2.0: {} + performance-now@2.1.0: {} + pg-cloudflare@1.1.1: optional: true @@ -21806,6 +24061,8 @@ snapshots: picomatch@4.0.2: {} + picomatch@4.0.3: {} + pidtree@0.6.0: {} pify@2.3.0: {} @@ -21860,6 +24117,12 @@ snapshots: mlly: 1.7.4 pathe: 2.0.3 + pkg-up@3.1.0: + dependencies: + find-up: 3.0.0 + + platform@1.3.6: {} + pluralize@8.0.0: {} pngjs@5.0.0: {} @@ -22024,8 +24287,25 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 + proxy-agent@6.5.0: + dependencies: + agent-base: 7.1.3 + debug: 4.4.3 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + lru-cache: 7.18.3 + pac-proxy-agent: 7.2.0 + proxy-from-env: 1.1.0 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + proxy-from-env@1.1.0: {} + psl@1.15.0: + dependencies: + punycode: 2.3.1 + pump@3.0.2: dependencies: end-of-stream: 1.4.4 @@ -22049,6 +24329,10 @@ snapshots: dependencies: side-channel: 1.1.0 + qs@6.5.3: {} + + quansync@1.0.0: {} + query-string@7.1.3: dependencies: decode-uri-component: 0.2.2 @@ -22549,6 +24833,29 @@ snapshots: request-ip@3.3.0: {} + request@2.88.2: + dependencies: + aws-sign2: 0.7.0 + aws4: 1.13.2 + caseless: 0.12.0 + combined-stream: 1.0.8 + extend: 3.0.2 + forever-agent: 0.6.1 + form-data: 2.3.3 + har-validator: 5.1.5 + http-signature: 1.2.0 + is-typedarray: 1.0.0 + isstream: 0.1.2 + json-stringify-safe: 5.0.1 + mime-types: 2.1.35 + oauth-sign: 0.9.0 + performance-now: 2.1.0 + qs: 6.5.3 + safe-buffer: 5.2.1 + tough-cookie: 2.5.0 + tunnel-agent: 0.6.0 + uuid: 3.4.0 + require-directory@2.1.1: {} require-from-string@2.0.2: {} @@ -22625,6 +24932,42 @@ snapshots: robust-predicates@3.0.2: {} + rolldown-plugin-dts@0.18.3(rolldown@1.0.0-beta.53)(typescript@5.9.3): + dependencies: + '@babel/generator': 7.28.5 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + ast-kit: 2.2.0 + birpc: 3.0.0 + dts-resolver: 2.1.3 + get-tsconfig: 4.13.0 + magic-string: 0.30.21 + obug: 2.1.1 + rolldown: 1.0.0-beta.53 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - oxc-resolver + + rolldown@1.0.0-beta.53: + dependencies: + '@oxc-project/types': 0.101.0 + '@rolldown/pluginutils': 1.0.0-beta.53 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-beta.53 + '@rolldown/binding-darwin-arm64': 1.0.0-beta.53 + '@rolldown/binding-darwin-x64': 1.0.0-beta.53 + '@rolldown/binding-freebsd-x64': 1.0.0-beta.53 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.53 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.53 + '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.53 + '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.53 + '@rolldown/binding-linux-x64-musl': 1.0.0-beta.53 + '@rolldown/binding-openharmony-arm64': 1.0.0-beta.53 + '@rolldown/binding-wasm32-wasi': 1.0.0-beta.53 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.53 + '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.53 + rollup@4.35.0: dependencies: '@types/estree': 1.0.6 @@ -22744,6 +25087,10 @@ snapshots: screenfull@5.2.0: {} + sdk-base@2.0.1: + dependencies: + get-ready: 1.0.0 + secure-json-parse@2.7.0: {} seek-bzip@1.0.6: @@ -22754,6 +25101,8 @@ snapshots: dependencies: semver: 7.7.2 + semver@5.7.2: {} + semver@6.3.1: {} semver@7.7.1: {} @@ -23028,6 +25377,18 @@ snapshots: sqlstring@2.3.3: {} + sshpk@1.18.0: + dependencies: + asn1: 0.2.6 + assert-plus: 1.0.0 + bcrypt-pbkdf: 1.0.2 + dashdash: 1.14.1 + ecc-jsbn: 0.1.2 + getpass: 0.1.7 + jsbn: 0.1.1 + safer-buffer: 2.1.2 + tweetnacl: 0.14.5 + ssri@10.0.6: dependencies: minipass: 7.1.2 @@ -23050,6 +25411,8 @@ snapshots: state-toggle@1.0.3: {} + statuses@1.5.0: {} + statuses@2.0.1: {} statuses@2.0.2: {} @@ -23060,12 +25423,27 @@ snapshots: dependencies: bl: 5.1.0 + stream-browserify@3.0.0: + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + stream-chain@2.2.5: {} + stream-http@2.8.2: + dependencies: + builtin-status-codes: 3.0.0 + inherits: 2.0.4 + readable-stream: 2.3.8 + to-arraybuffer: 1.0.1 + xtend: 4.0.2 + stream-json@1.9.1: dependencies: stream-chain: 2.2.5 + stream-wormhole@1.1.0: {} + streamsearch@1.1.0: {} streamx@2.22.0: @@ -23201,6 +25579,8 @@ snapshots: strnum@1.1.2: {} + strnum@2.1.2: {} + strtok3@9.1.1: dependencies: '@tokenizer/token': 0.3.0 @@ -23443,11 +25823,18 @@ snapshots: tinyexec@0.3.2: {} + tinyexec@1.0.2: {} + tinyglobby@0.2.12: dependencies: fdir: 6.4.3(picomatch@4.0.2) picomatch: 4.0.2 + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + tinypool@0.8.4: {} tinypool@1.0.2: {} @@ -23464,6 +25851,8 @@ snapshots: tmpl@1.0.5: {} + to-arraybuffer@1.0.1: {} + to-buffer@1.1.1: {} to-regex-range@5.0.1: @@ -23483,6 +25872,11 @@ snapshots: totalist@3.0.1: {} + tough-cookie@2.5.0: + dependencies: + psl: 1.15.0 + punycode: 2.3.1 + tr46@0.0.3: {} tr46@5.1.0: @@ -23580,6 +25974,32 @@ snapshots: minimist: 1.2.8 strip-bom: 3.0.0 + tsdown@0.17.4(typescript@5.9.3): + dependencies: + ansis: 4.2.0 + cac: 6.7.14 + defu: 6.1.4 + empathic: 2.0.0 + hookable: 5.5.3 + import-without-cache: 0.2.3 + obug: 2.1.1 + rolldown: 1.0.0-beta.53 + rolldown-plugin-dts: 0.18.3(rolldown@1.0.0-beta.53)(typescript@5.9.3) + semver: 7.7.3 + tinyexec: 1.0.2 + tinyglobby: 0.2.15 + tree-kill: 1.2.2 + unconfig-core: 7.4.2 + unrun: 0.2.19 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - '@ts-macro/tsc' + - '@typescript/native-preview' + - oxc-resolver + - synckit + - vue-tsc + tslib@2.3.0: {} tslib@2.4.0: {} @@ -23603,6 +26023,8 @@ snapshots: dependencies: '@mixmark-io/domino': 2.2.0 + tweetnacl@0.14.5: {} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -23677,6 +26099,8 @@ snapshots: typescript@5.8.2: {} + typescript@5.9.3: {} + ufo@1.5.4: {} uid@2.0.2: @@ -23697,6 +26121,11 @@ snapshots: buffer: 5.7.1 through: 2.3.8 + unconfig-core@7.4.2: + dependencies: + '@quansync/fs': 1.0.0 + quansync: 1.0.0 + underscore@1.13.7: {} undici-types@5.26.5: {} @@ -23708,6 +26137,10 @@ snapshots: undici-types@7.8.0: optional: true + unescape@1.0.1: + dependencies: + extend-shallow: 2.0.1 + unhead@1.11.20: dependencies: '@unhead/dom': 1.11.20 @@ -23821,6 +26254,10 @@ snapshots: unpipe@1.0.0: {} + unrun@0.2.19: + dependencies: + rolldown: 1.0.0-beta.53 + update-browserslist-db@1.1.3(browserslist@4.24.4): dependencies: browserslist: 4.24.4 @@ -23848,6 +26285,21 @@ snapshots: dependencies: punycode: 2.3.1 + urllib@2.44.0: + dependencies: + any-promise: 1.3.0 + content-type: 1.0.5 + default-user-agent: 1.0.0 + digest-header: 1.1.0 + ee-first: 1.1.1 + formstream: 1.5.2 + humanize-ms: 1.2.1 + iconv-lite: 0.6.3 + pump: 3.0.2 + qs: 6.14.0 + statuses: 1.5.0 + utility: 1.18.0 + use-callback-ref@1.3.3(@types/react@18.3.1)(react@18.3.1): dependencies: react: 18.3.1 @@ -23907,8 +26359,18 @@ snapshots: is-typed-array: 1.1.15 which-typed-array: 1.1.19 + utility@1.18.0: + dependencies: + copy-to: 2.0.1 + escape-html: 1.0.3 + mkdirp: 0.5.6 + mz: 2.7.0 + unescape: 1.0.1 + utils-merge@1.0.1: {} + uuid@3.4.0: {} + uuid@8.3.2: {} uuid@9.0.1: {} @@ -23930,6 +26392,12 @@ snapshots: vary@1.1.2: {} + verror@1.10.0: + dependencies: + assert-plus: 1.0.0 + core-util-is: 1.0.2 + extsprintf: 1.3.0 + vfile-location@2.0.6: {} vfile-location@5.0.3: @@ -24115,7 +26583,7 @@ snapshots: vitest@3.1.1(@types/debug@4.1.12)(@types/node@20.17.24)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.8.1): dependencies: '@vitest/expect': 3.1.1 - '@vitest/mocker': 3.1.1(vite@6.2.2(@types/node@20.17.24)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.8.1)) + '@vitest/mocker': 3.1.1(vite@6.2.2(@types/node@24.0.13)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.8.1)) '@vitest/pretty-format': 3.1.1 '@vitest/runner': 3.1.1 '@vitest/snapshot': 3.1.1 @@ -24381,6 +26849,10 @@ snapshots: dependencies: string-width: 5.1.2 + win-release@1.1.1: + dependencies: + semver: 5.7.2 + winston-transport@4.9.0: dependencies: logform: 2.7.0 @@ -24560,14 +27032,12 @@ snapshots: dependencies: zod: 4.1.12 - zod-validation-error@3.4.0(zod@3.25.51): + zod-validation-error@3.4.0(zod@3.25.76): dependencies: - zod: 3.25.51 + zod: 3.25.76 zod@3.24.1: {} - zod@3.25.51: {} - zod@3.25.76: {} zod@4.1.11: {} diff --git a/projects/app/.env.template b/projects/app/.env.template index d50a573cb..91467af4e 100644 --- a/projects/app/.env.template +++ b/projects/app/.env.template @@ -34,18 +34,6 @@ AIPROXY_API_TOKEN=aiproxy # OPENAI_BASE_URL=https://api.openai.com/v1 # CHAT_API_KEY=sk-xxxx -# S3 Config -S3_EXTERNAL_BASE_URL= -S3_ENDPOINT=localhost -S3_PORT=9000 -S3_USE_SSL=false -S3_ACCESS_KEY=minioadmin -S3_SECRET_KEY=minioadmin -S3_PUBLIC_BUCKET=fastgpt-public # 插件文件存储公开桶 -S3_PRIVATE_BUCKET=fastgpt-private # 插件文件存储公开桶 -S3_PATH_STYLE=true # forcePathStyle 默认为 true, 当且仅当设置为 false 时关闭, 其他值都为 true -S3_REGION= # 如果是本地部署的 MinIO等服务就不需要;如果是云服务就需要,比如 aws 的或者国内 oss 厂商 - # Redis URL REDIS_URL=redis://default:mypassword@127.0.0.1:6379 # mongo 数据库连接参数,本地开发连接远程数据库时,可能需要增加 directConnection=true 参数,才能连接上。 @@ -121,3 +109,62 @@ CONFIG_JSON_PATH= # CHAT_LOG_INTERVAL=10000 # # 日志来源ID前缀 # CHAT_LOG_SOURCE_ID_PREFIX=fastgpt- + +# ✅ 对象存储供应商 +# - minio: MinIO / 或者其他兼容 S3 协议的自部署对象存储服务 +# - aws-s3: AWS S3 +# - oss: 阿里云 OSS +# - cos: 腾讯云 COS +STORAGE_VENDOR=minio +# 地区 +# - minio: 通常本地部署的对象存储服务的地区设置没什么影响 比如设置为 "us-east-1" 就可以了 +# - aws-s3: 根据云服务商提供的设置 比如 "ap-northeast-1" +# - oss: 根据云服务商提供的设置 比如 "oss-cn-hangzhou" +# - cos: 根据云服务商提供的设置 比如 "ap-shanghai" +STORAGE_REGION=us-east-1 +# 身份验证凭证 +STORAGE_ACCESS_KEY_ID=minioadmin +STORAGE_SECRET_ACCESS_KEY=minioadmin +# 存储桶名称 +# - 公开桶 +# - 私有桶 +STORAGE_PUBLIC_BUCKET=fastgpt-public +STORAGE_PRIVATE_BUCKET=fastgpt-private +# 一个公开的、前端和用户可以直接访问的对象存储连接 +# - 比如 MinIO 的反向代理链接或者一个 CDN: https://s3.example.com +STORAGE_EXTERNAL_BASE_URL= +# ️⭕ 兼容 S3 协议的对象存储需要额外填的 +# S3 端点连接 URL 为了避免歧义 填写完整的、包含协议与端口的 URL +# - 本地 MinIO: http://127.0.0.1:9000 +# - docker-compose 中的 MinIO: http://fastgpt-minio:9000 +STORAGE_S3_ENDPOINT=http://127.0.0.1:9000 +# 路径风格配置 (virtual-host style | path style) +# - true => http(s)://endpoint/{bucket}/{key} +# - false => http(s)://{bucket}.endpoint/{key} +STORAGE_S3_FORCE_PATH_STYLE=true +# 【可选】最多请求重试次数 +STORAGE_S3_MAX_RETRIES=3 +# ️⭕ 阿里云 OSS 需要额外填的 参考: https://github.com/ali-sdk/ali-oss?tab=readme-ov-file#ossoptions +# 阿里云连接端点 URL +# - 比如 oss-cn-hangzhou.aliyuncs.com +# - 如果配置了 CName 记得更换为映射的域名 比如 http(s)://example.com +STORAGE_OSS_ENDPOINT=oss-cn-hangzhou.aliyuncs.com +# 【可选】自定义域名 CNAME 参考: https://help.aliyun.com/zh/oss/developer-reference/initialization-10?spm=a2c4g.11186623.help-menu-31815.d_1_1_10_1.34ec79cfj3YO6w&scm=20140722.H_111256._.OR_help-T_cn~zh-V_1#9635d0c28f3p6 +STORAGE_OSS_CNAME=false +# 【可选】是否开启 TLS +# - true +# - false +STORAGE_OSS_SECURE=false +# 【可选】Whether to use internal endpoint (intra-cloud) +STORAGE_OSS_INTERNAL=false +# ️⭕ 腾讯云 COS 需要额外填的 参考: https://cloud.tencent.com/document/product/436/8629#.E9.85.8D.E7.BD.AE.E9.A1.B9 +# 【可选】发请求时用的协议,可选项 https:、http: 默认判断当前页面是 http: 时使用 http: 否则使用 https: +# - http: +# - https: +STORAGE_COS_PROTOCOL=http: +# 【可选】是否启用全球加速域名 默认为 false 若改为 true 需要存储桶开启全球加速功能 +STORAGE_COS_USE_ACCELERATE=false +# 【可选】CNAME 的自定义域名 +STORAGE_COS_CNAME_DOMAIN= +# 【可选】请求时使用 HTTP 代理,例如:http://127.0.0.1:8080 +STORAGE_COS_PROXY= diff --git a/projects/app/src/components/core/app/FileSelector/index.tsx b/projects/app/src/components/core/app/FileSelector/index.tsx index 5e73e7569..dad0e1d6f 100644 --- a/projects/app/src/components/core/app/FileSelector/index.tsx +++ b/projects/app/src/components/core/app/FileSelector/index.tsx @@ -26,7 +26,7 @@ import MyAvatar from '@fastgpt/web/components/common/Avatar'; import { z } from 'zod'; import { getPresignedChatFileGetUrl, getUploadChatFilePresignedUrl } from '@/web/common/file/api'; import { useContextSelector } from 'use-context-selector'; -import { POST } from '@/web/common/api/request'; +import { PUT } from '@/web/common/api/request'; import { getErrText } from '@fastgpt/global/common/error/utils'; import { formatFileSize } from '@fastgpt/global/common/file/tools'; import { WorkflowRuntimeContext } from '@/components/core/chat/ChatContainer/context/workflowRuntimeContext'; @@ -111,7 +111,10 @@ const FileSelector = ({ try { // Get Upload Post Presigned URL - const { url, fields } = await getUploadChatFilePresignedUrl({ + const { + url, + fields: { key, ...headers } + } = await getUploadChatFilePresignedUrl({ filename: file.rawFile.name, appId, chatId, @@ -119,10 +122,10 @@ const FileSelector = ({ }); // Upload File to S3 - const formData = new FormData(); - Object.entries(fields).forEach(([k, v]) => formData.set(k, v)); - formData.set('file', file.rawFile); - await POST(url, formData, { + await PUT(url, file.rawFile, { + headers: { + ...headers + }, onUploadProgress: (e) => { if (!e.total) return; const percent = Math.round((e.loaded / e.total) * 100); @@ -136,7 +139,7 @@ const FileSelector = ({ timeout: 5 * 60 * 1000 // 5 minutes }); const previewUrl = await getPresignedChatFileGetUrl({ - key: fields.key, + key: key, appId, outLinkAuthData }); @@ -145,7 +148,7 @@ const FileSelector = ({ files.forEach((item) => { if (item.id === file.id) { item.url = previewUrl; - item.key = fields.key; + item.key = key; item.process = 100; } }); diff --git a/projects/app/src/components/core/chat/ChatContainer/ChatBox/hooks/useFileUpload.tsx b/projects/app/src/components/core/chat/ChatContainer/ChatBox/hooks/useFileUpload.tsx index b60071a91..dc11a353c 100644 --- a/projects/app/src/components/core/chat/ChatContainer/ChatBox/hooks/useFileUpload.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/ChatBox/hooks/useFileUpload.tsx @@ -14,7 +14,7 @@ import { type AppFileSelectConfigType } from '@fastgpt/global/core/app/type'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { type OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat'; import { getPresignedChatFileGetUrl, getUploadChatFilePresignedUrl } from '@/web/common/file/api'; -import { POST } from '@/web/common/api/request'; +import { PUT } from '@/web/common/api/request'; import { getUploadFileType } from '@fastgpt/global/core/app/constants'; import { parseS3UploadError } from '@fastgpt/global/common/error/s3'; @@ -176,7 +176,11 @@ export const useFileUpload = (props: UseFileUploadOptions) => { const fileIndex = fileList.findIndex((item) => item.id === file.id)!; // Get Upload Post Presigned URL - const { url, fields, maxSize } = await getUploadChatFilePresignedUrl({ + const { + url, + fields: { key, ...headers }, + maxSize + } = await getUploadChatFilePresignedUrl({ filename: copyFile.rawFile.name, appId, chatId, @@ -184,10 +188,10 @@ export const useFileUpload = (props: UseFileUploadOptions) => { }); // Upload File to S3 - const formData = new FormData(); - Object.entries(fields).forEach(([k, v]) => formData.set(k, v)); - formData.set('file', copyFile.rawFile); - await POST(url, formData, { + await PUT(url, copyFile.rawFile, { + headers: { + ...headers + }, onUploadProgress: (e) => { if (!e.total) return; const percent = Math.round((e.loaded / e.total) * 100); @@ -198,14 +202,14 @@ export const useFileUpload = (props: UseFileUploadOptions) => { }).catch((error) => Promise.reject(parseS3UploadError({ t, error, maxSize }))); const previewUrl = await getPresignedChatFileGetUrl({ - key: fields.key, + key: key, appId, outLinkAuthData }); // Update file url and key copyFile.url = previewUrl; - copyFile.key = fields.key; + copyFile.key = key; updateFiles(fileIndex, copyFile); } catch (error) { errorFileIndex.push(fileList.findIndex((item) => item.id === file.id)!); diff --git a/projects/app/src/pageComponents/app/detail/components/QuickCreateDatasetModal.tsx b/projects/app/src/pageComponents/app/detail/components/QuickCreateDatasetModal.tsx index e55103fd4..d89b55b5d 100644 --- a/projects/app/src/pageComponents/app/detail/components/QuickCreateDatasetModal.tsx +++ b/projects/app/src/pageComponents/app/detail/components/QuickCreateDatasetModal.tsx @@ -20,7 +20,7 @@ import { useUploadAvatar } from '@fastgpt/web/common/file/hooks/useUploadAvatar' import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import { postCreateDatasetWithFiles, getDatasetById } from '@/web/core/dataset/api'; import { getUploadAvatarPresignedUrl, getUploadTempFilePresignedUrl } from '@/web/common/file/api'; -import { POST } from '@/web/common/api/request'; +import { PUT } from '@/web/common/api/request'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { getWebDefaultEmbeddingModel, getWebDefaultLLMModel } from '@/web/common/system/utils'; import { getErrText } from '@fastgpt/global/common/error/utils'; @@ -82,15 +82,18 @@ const QuickCreateDatasetModal = ({ await Promise.all( files.map(async ({ fileId, file }) => { try { - const { url, fields, maxSize } = await getUploadTempFilePresignedUrl({ + const { + url, + fields: { key, ...headers }, + maxSize + } = await getUploadTempFilePresignedUrl({ filename: file.name }); - const formData = new FormData(); - Object.entries(fields).forEach(([k, v]) => formData.set(k, v)); - formData.set('file', file); - - await POST(url, formData, { + await PUT(url, file, { + headers: { + ...headers + }, onUploadProgress: (e) => { if (!e.total) return; const percent = Math.round((e.loaded / e.total) * 100); @@ -115,7 +118,7 @@ const QuickCreateDatasetModal = ({ item.id === fileId ? { ...item, - dbFileId: fields.key, + dbFileId: key, isUploading: false, uploadedFileRate: 100 } diff --git a/projects/app/src/pageComponents/config/ImportPluginModal.tsx b/projects/app/src/pageComponents/config/ImportPluginModal.tsx index ecbdbc8e2..b0c046416 100644 --- a/projects/app/src/pageComponents/config/ImportPluginModal.tsx +++ b/projects/app/src/pageComponents/config/ImportPluginModal.tsx @@ -55,21 +55,17 @@ const ImportPluginModal = ({ ) ); - const presignedData = await getPkgPluginUploadURL({ filename: file.name }); - - const formData = new FormData(); - Object.entries(presignedData.formData).forEach(([key, value]) => { - formData.append(key, value); + const { formData, objectName, postURL } = await getPkgPluginUploadURL({ + filename: file.name }); - formData.append('file', file.file); - await postS3UploadFile(presignedData.postURL, formData); + await postS3UploadFile(postURL, file.file, { ...formData }); setUploadedFiles((prev) => prev.map((f) => (f.name === file.name ? { ...f, status: 'parsing' } : f)) ); - const parseResult = await parseUploadedPkgPlugin({ objectName: presignedData.objectName }); + const parseResult = await parseUploadedPkgPlugin({ objectName }); const parentId = parseResult.find((item) => !item.parentId)?.toolId; if (!parentId) { diff --git a/projects/app/src/pageComponents/dataset/detail/Import/diffSource/FileLocal.tsx b/projects/app/src/pageComponents/dataset/detail/Import/diffSource/FileLocal.tsx index e0a93f8af..082aee8e2 100644 --- a/projects/app/src/pageComponents/dataset/detail/Import/diffSource/FileLocal.tsx +++ b/projects/app/src/pageComponents/dataset/detail/Import/diffSource/FileLocal.tsx @@ -14,7 +14,7 @@ import { formatFileSize } from '@fastgpt/global/common/file/tools'; import { getFileIcon } from '@fastgpt/global/common/file/icon'; import { DatasetPageContext } from '@/web/core/dataset/context/datasetPageContext'; import { getUploadDatasetFilePresignedUrl } from '@/web/common/file/api'; -import { POST } from '@/web/common/api/request'; +import { PUT } from '@/web/common/api/request'; import { parseS3UploadError } from '@fastgpt/global/common/error/s3'; const DataProcess = dynamic(() => import('../commonProgress/DataProcess')); @@ -68,16 +68,20 @@ const SelectFile = React.memo(function SelectFile() { await Promise.all( files.map(async ({ fileId, file }) => { try { - const { url, fields, maxSize } = await getUploadDatasetFilePresignedUrl({ + const { + url, + fields: { key, ...headers }, + maxSize + } = await getUploadDatasetFilePresignedUrl({ filename: file.name, datasetId }); // Upload File to S3 - const formData = new FormData(); - Object.entries(fields).forEach(([k, v]) => formData.set(k, v)); - formData.set('file', file); - await POST(url, formData, { + await PUT(url, file, { + headers: { + ...headers + }, onUploadProgress: (e) => { if (!e.total) return; const percent = Math.round((e.loaded / e.total) * 100); @@ -102,7 +106,7 @@ const SelectFile = React.memo(function SelectFile() { item.id === fileId ? { ...item, - dbFileId: fields.key, + dbFileId: key, isUploading: false, uploadedFileRate: 100 } diff --git a/projects/app/src/pages/api/common/file/presignTempFilePostUrl.ts b/projects/app/src/pages/api/common/file/presignTempFilePostUrl.ts index 243fa5087..11bceb7c6 100644 --- a/projects/app/src/pages/api/common/file/presignTempFilePostUrl.ts +++ b/projects/app/src/pages/api/common/file/presignTempFilePostUrl.ts @@ -38,7 +38,7 @@ async function handler( const bucket = new S3PrivateBucket(); const { fileKey } = getFileS3Key.temp({ teamId, filename }); - return await bucket.createPostPresignedUrl({ rawKey: fileKey, filename }, { expiredHours: 1 }); + return await bucket.createPresignedPutUrl({ rawKey: fileKey, filename }, { expiredHours: 1 }); } export default NextAPI(handler); diff --git a/projects/app/src/pages/api/common/file/read/[filename].ts b/projects/app/src/pages/api/common/file/read/[filename].ts index 8b26df479..5f0f7f02a 100644 --- a/projects/app/src/pages/api/common/file/read/[filename].ts +++ b/projects/app/src/pages/api/common/file/read/[filename].ts @@ -34,7 +34,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< getS3DatasetSource().getFileStream(fileId) ]); - if (!file) { + if (!file || !fileStream) { return Promise.reject(CommonErrEnum.fileNotFound); } @@ -49,7 +49,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< 'Content-Disposition', `${disposition}; filename="${encodeURIComponent(filename)}"` ); - res.setHeader('Content-Length', file.contentLength); + if (file.contentLength) { + res.setHeader('Content-Length', file.contentLength); + } stream.pipe(res); diff --git a/projects/app/src/pages/api/core/chat/presignChatFileGetUrl.ts b/projects/app/src/pages/api/core/chat/presignChatFileGetUrl.ts index 5658d1dca..a4b881014 100644 --- a/projects/app/src/pages/api/core/chat/presignChatFileGetUrl.ts +++ b/projects/app/src/pages/api/core/chat/presignChatFileGetUrl.ts @@ -15,7 +15,9 @@ async function handler(req: ApiRequestProps): Promi ...outLinkAuthData }); - return await getS3ChatSource().createGetChatFileURL({ key, external: true }); + const { getUrl: url } = await getS3ChatSource().createGetChatFileURL({ key, external: true }); + + return url; } export default NextAPI(handler); diff --git a/projects/app/src/pages/api/core/dataset/collection/read.ts b/projects/app/src/pages/api/core/dataset/collection/read.ts index 9c9e03577..a4c77983e 100644 --- a/projects/app/src/pages/api/core/dataset/collection/read.ts +++ b/projects/app/src/pages/api/core/dataset/collection/read.ts @@ -79,11 +79,13 @@ async function handler( collection.fileId && isS3ObjectKey(collection.fileId, 'dataset') ) { - return getS3DatasetSource().createGetDatasetFileURL({ - key: collection.fileId, - expiredHours: 1, - external: true - }); + return ( + await getS3DatasetSource().createGetDatasetFileURL({ + key: collection.fileId, + expiredHours: 1, + external: true + }) + ).getUrl; } if (collection.type === DatasetCollectionTypeEnum.link && collection.rawLink) { return collection.rawLink; diff --git a/projects/app/src/pages/api/core/dataset/data/v2/list.ts b/projects/app/src/pages/api/core/dataset/data/v2/list.ts index 59f29b175..223dc6e1b 100644 --- a/projects/app/src/pages/api/core/dataset/data/v2/list.ts +++ b/projects/app/src/pages/api/core/dataset/data/v2/list.ts @@ -83,7 +83,7 @@ async function handler( const s3ImageIds = imageIds.filter((id) => isS3ObjectKey(id, 'dataset')); for (const id of s3ImageIds) { const metadata = await getS3DatasetSource().getFileMetadata(id); - if (metadata) { + if (metadata?.contentLength) { imageSizeMap.set(id, metadata.contentLength); } } diff --git a/projects/app/src/pages/api/system/file/[jwt].ts b/projects/app/src/pages/api/system/file/[jwt].ts index 35740129a..74d700a16 100644 --- a/projects/app/src/pages/api/system/file/[jwt].ts +++ b/projects/app/src/pages/api/system/file/[jwt].ts @@ -32,8 +32,17 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) })() ); + if (!stream) { + return jsonRes(res, { + code: 404, + error: 'File not found' + }); + } + if (metadata) { res.setHeader('Content-Type', metadata.contentType); + } + if (metadata?.contentLength) { res.setHeader('Content-Length', metadata.contentLength); } res.setHeader('Cache-Control', 'public, max-age=31536000'); diff --git a/projects/app/src/web/common/api/request.ts b/projects/app/src/web/common/api/request.ts index 53282e268..f45f3fc57 100644 --- a/projects/app/src/web/common/api/request.ts +++ b/projects/app/src/web/common/api/request.ts @@ -179,13 +179,15 @@ function request( { cancelToken, maxQuantity, withCredentials, ...config }: ConfigType, method: Method ): any { - /* 去空 */ - for (const key in data) { - const val = data[key]; - if (data[key] === undefined) { - delete data[key]; - } else if (val instanceof Date) { - data[key] = dayjs(val).format(); + if (!(data instanceof Blob)) { + /* 去空 */ + for (const key in data) { + const val = data[key]; + if (data[key] === undefined) { + delete data[key]; + } else if (val instanceof Date) { + data[key] = dayjs(val).format(); + } } } diff --git a/projects/app/src/web/common/file/api.ts b/projects/app/src/web/common/file/api.ts index 5800b9e68..a92b89376 100644 --- a/projects/app/src/web/common/file/api.ts +++ b/projects/app/src/web/common/file/api.ts @@ -1,16 +1,18 @@ -import { POST } from '@/web/common/api/request'; +import { POST, PUT } from '@/web/common/api/request'; import type { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat'; import type { CreatePostPresignedUrlResult } from '@fastgpt/service/common/s3/type'; import { type AxiosProgressEvent } from 'axios'; export const postS3UploadFile = ( postURL: string, - form: FormData, + file: File, + headers?: Record, onUploadProgress?: (progressEvent: AxiosProgressEvent) => void ) => - POST(postURL, form, { + PUT(postURL, file, { timeout: 600000, - onUploadProgress + onUploadProgress, + ...(headers ? { headers } : {}) }); export const getUploadAvatarPresignedUrl = (params: { diff --git a/tsconfig.json b/tsconfig.json index 2a98c4faf..87f03da4b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es2022", + "target": "esnext", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, @@ -9,7 +9,7 @@ "noEmit": true, "esModuleInterop": true, "module": "esnext", - "moduleResolution": "node", + "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve",