diff --git a/package.json b/package.json index 7a0259598..f6c12de62 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,10 @@ "postinstall": "patch-package" }, "dependencies": { + "@aws-sdk/client-s3": "^3.1125.0", + "@aws-sdk/lib-storage": "^3.1125.0", + "@aws-sdk/s3-presigned-post": "^3.1125.0", + "@aws-sdk/s3-request-presigner": "^3.1125.0", "@bull-board/api": "^6.3.0", "@bull-board/express": "^6.3.0", "@bull-board/nestjs": "^6.3.0", @@ -58,10 +62,10 @@ "connect-redis": "^7.1.0", "discord.js": "^14.14.1", "express-session": "^1.18.0", + "files-sdk": "^2.3.0", "globaloffensive": "^3.0.2", "ioredis": "^5.6.1", "jsonwebtoken": "^9.0.2", - "minio": "^8.0.1", "minisearch": "^7.1.0", "oauth": "^0.10.0", "openpgp": "^6.1.1", diff --git a/src/configs/s3.ts b/src/configs/s3.ts index 36203b737..dd28fef2d 100644 --- a/src/configs/s3.ts +++ b/src/configs/s3.ts @@ -8,8 +8,16 @@ export default (): { secret: process.env.S3_SECRET, bucket: process.env.S3_BUCKET, db_backup_bucket: process.env.S3_DB_BACKUP_BUCKET || "5stack-db-backups", - endpoint: process.env.S3_ENDPOINT || "minio", + endpoint: process.env.S3_ENDPOINT || "rustfs", + // SigV4 puts the region in the credential scope, so a remote bucket whose + // region this does not match rejects every signature. The in-cluster store + // accepts any region, which is why this can have a default at all. + region: process.env.S3_REGION || "us-east-1", useSSL: process.env.S3_USE_SSL === "true" ? true : false, + // AWS dropped path-style addressing for buckets created after Sept 2020, + // so a real AWS endpoint needs this off. Every other S3 implementation + // 5stack targets accepts path style, and the in-cluster store requires it. + forcePathStyle: process.env.S3_FORCE_PATH_STYLE !== "false", port: process.env.S3_PORT || "9000", }, }); diff --git a/src/configs/types/S3Config.ts b/src/configs/types/S3Config.ts index 68cb00b48..0a681e920 100644 --- a/src/configs/types/S3Config.ts +++ b/src/configs/types/S3Config.ts @@ -4,6 +4,8 @@ export type S3Config = { bucket: string; db_backup_bucket: string; endpoint: string; + region: string; useSSL: boolean; + forcePathStyle: boolean; port: string; }; diff --git a/src/s3-scan/s3-scan.service.ts b/src/s3-scan/s3-scan.service.ts index 95c2f04d7..a15aa6404 100644 --- a/src/s3-scan/s3-scan.service.ts +++ b/src/s3-scan/s3-scan.service.ts @@ -1,5 +1,4 @@ import { Injectable, Logger } from "@nestjs/common"; -import { ObjectInfo } from "minio/dist/main/internal/type"; import { e_notification_types_enum, e_player_roles_enum, @@ -105,8 +104,7 @@ export class S3ScanService { const sizeByKey = new Map(); const stream = this.s3.listStream(); - for await (const entry of stream) { - const obj = entry as ObjectInfo; + for await (const obj of stream) { const key = obj.name; if (!key) { continue; diff --git a/src/s3/s3.service.spec.ts b/src/s3/s3.service.spec.ts new file mode 100644 index 000000000..04f7d9745 --- /dev/null +++ b/src/s3/s3.service.spec.ts @@ -0,0 +1,136 @@ +import { S3Service } from "./s3.service"; + +const DEMOS_DOMAIN = "demos.example.com"; + +const build = ( + endpoint: string, + port: string, + useSSL: boolean, + overrides: { region?: string; forcePathStyle?: boolean } = {}, +) => { + const logger = { log: jest.fn(), warn: jest.fn(), error: jest.fn() }; + + const config = { + get: () => ({ + key: "access-key", + secret: "secret-key", + bucket: "5stack", + db_backup_bucket: "5stack-db-backups", + endpoint, + region: "us-east-1", + useSSL, + forcePathStyle: true, + port, + ...overrides, + }), + }; + + return new S3Service(logger as never, config as never); +}; + +const hostOf = (url: string) => new URL(url).host; + +// Exercised through getPresignedPartUrl because it shares endpointFor() and +// isInternalStore with every other signing path while staying on the AWS SDK. +// The files-sdk paths cannot be reached from here: it is ESM-only, and a real +// dynamic import inside jest's VM needs --experimental-vm-modules. +describe("S3Service presigned url routing", () => { + const originalDomain = process.env.DEMOS_DOMAIN; + + beforeAll(() => { + process.env.DEMOS_DOMAIN = DEMOS_DOMAIN; + }); + + afterAll(() => { + // Assigning undefined would store the string "undefined" and leak that + // into every later test in this worker. + if (originalDomain === undefined) { + delete process.env.DEMOS_DOMAIN; + return; + } + + process.env.DEMOS_DOMAIN = originalDomain; + }); + + // A URL signed against either in-cluster name is unreachable from the + // browser doing the upload, so both have to route to the demos domain. + describe.each(["rustfs", "minio"])("with S3_ENDPOINT=%s", (endpoint) => { + it("signs multipart part uploads against the public demos domain", async () => { + const url = await build(endpoint, "9000", false).getPresignedPartUrl( + "key", + "upload-id", + 1, + 60, + ); + + expect(hostOf(url)).toBe(DEMOS_DOMAIN); + }); + + it("carries the upload id and part number into the signature", async () => { + const url = await build(endpoint, "9000", false).getPresignedPartUrl( + "demos/match/big.dem", + "upload-id", + 7, + 60, + ); + + const params = new URL(url).searchParams; + + expect(params.get("uploadId")).toBe("upload-id"); + expect(params.get("partNumber")).toBe("7"); + }); + }); + + describe("with a remote bucket", () => { + const endpoint = "s3.us-east-005.backblazeb2.com"; + + it("signs against the remote host, not the demos domain", async () => { + const url = await build(endpoint, "443", true).getPresignedPartUrl( + "key", + "upload-id", + 1, + 60, + ); + + expect(hostOf(url)).toBe(endpoint); + }); + + // A region that does not match the endpoint's puts the wrong scope in the + // signature, and the store rejects every signed request. + it("signs with the configured region", async () => { + const url = await build(endpoint, "443", true, { + region: "us-east-005", + }).getPresignedPartUrl("key", "upload-id", 1, 60); + + const credential = new URL(url).searchParams.get( + "X-Amz-Credential", + ) as string; + + expect(credential).toContain("/us-east-005/s3/aws4_request"); + }); + + it("addresses the bucket virtual-host style when path style is off", async () => { + const url = await build(endpoint, "443", true, { + forcePathStyle: false, + }).getPresignedPartUrl("key", "upload-id", 1, 60); + + expect(hostOf(url)).toBe(`5stack.${endpoint}`); + }); + }); + + // Path style is forced for the in-cluster store regardless of config: it is + // reached by Service name, and no DNS answers a bucket subdomain of it. + describe.each(["rustfs", "minio"])( + "with S3_ENDPOINT=%s and path style disabled", + (endpoint) => { + it("still addresses the bucket path style", async () => { + const url = await build(endpoint, "9000", false, { + forcePathStyle: false, + }).getPresignedPartUrl("key", "upload-id", 1, 60); + + expect(hostOf(url)).toBe(DEMOS_DOMAIN); + expect(new URL(url).pathname).toBe("/5stack/key"); + }); + }, + ); +}); diff --git a/src/s3/s3.service.ts b/src/s3/s3.service.ts index 417d81e22..9465a386b 100644 --- a/src/s3/s3.service.ts +++ b/src/s3/s3.service.ts @@ -1,45 +1,192 @@ -import { Client } from "minio"; import { Readable } from "stream"; import { Request } from "express"; import { ConfigService } from "@nestjs/config"; import { S3Config } from "../configs/types/S3Config"; -import { Injectable, Logger } from "@nestjs/common"; -import { ObjectInfo } from "minio/dist/main/internal/type"; +import { Injectable, Logger, OnModuleDestroy } from "@nestjs/common"; +import { + AbortMultipartUploadCommand, + CompleteMultipartUploadCommand, + CreateMultipartUploadCommand, + DeleteObjectsCommand, + ListObjectVersionsCommand, + ListPartsCommand, + S3Client, + UploadPartCommand, +} from "@aws-sdk/client-s3"; +import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; + +export interface S3ObjectInfo { + name: string; + size: number; + lastModified?: Date; + etag?: string; +} -@Injectable() -export class S3Service { - private client: Client; - private externalClient: Client; +export interface S3StatInfo { + size: number; + etag?: string; + lastModified?: Date; + metaData: Record; +} + +type FilesSdk = typeof import("files-sdk"); +type Files = InstanceType; +type StoredFile = import("files-sdk").StoredFile; + +interface S3Modules { + Files: FilesSdk["Files"]; + s3: (options: Record) => never; +} + +// files-sdk is ESM-only -- its package exports declare no `require` condition, +// so a plain import compiled to CJS dies with ERR_PACKAGE_PATH_NOT_EXPORTED. +// The api is a CommonJS NestJS build, and tsc rewrites a literal `import()` in +// that mode into exactly the `require()` that cannot work. Going through the +// Function constructor is what keeps a genuine dynamic import in the output. +const importESM = new Function("specifier", "return import(specifier)") as ( + specifier: string, +) => Promise; +@Injectable() +export class S3Service implements OnModuleDestroy { private bucket: string; private config: S3Config; + private modules?: Promise; + + private readonly clients = new Map(); + private readonly rawClients = new Map(); constructor( private readonly logger: Logger, private readonly configService: ConfigService, ) { this.config = this.configService.get("s3"); - this.bucket = this.config.bucket; - this.client = new Client({ - port: parseInt(this.config.port), - endPoint: this.config.endpoint, - useSSL: this.config.useSSL, - accessKey: this.config.key, - secretKey: this.config.secret, + } + + public get bucketName(): string { + return this.bucket; + } + + // Loaded on first use rather than in the constructor: a dynamic import + // cannot run inside jest's VM without --experimental-vm-modules, and an + // eager one would make every test that merely constructs this service fail. + private loadModules(): Promise { + if (!this.modules) { + this.modules = Promise.all([ + importESM("files-sdk"), + importESM<{ s3: S3Modules["s3"] }>("files-sdk/s3"), + ]).then(([core, adapter]) => ({ Files: core.Files, s3: adapter.s3 })); + } + + return this.modules; + } + + private endpointFor(external: boolean): string { + if (external) { + return `https://${process.env.DEMOS_DOMAIN}`; + } + + const protocol = this.config.useSSL ? "https" : "http"; + + return `${protocol}://${this.config.endpoint}:${this.config.port}`; + } + + private get credentials() { + return { + accessKeyId: this.config.key, + secretAccessKey: this.config.secret, + }; + } + + // Both names are the in-cluster store: the panel keeps a minio Service + // aliased onto the rustfs pods for installs that still carry + // S3_ENDPOINT=minio. Anything else is a real remote bucket. + private get isInternalStore(): boolean { + return this.config.endpoint === "rustfs" || this.config.endpoint === "minio"; + } + + // Path style is not negotiable for the in-cluster store: it is addressed by + // a Service name, and virtual-host style would look for a bucket subdomain + // of it that no DNS answers. + private get forcePathStyle(): boolean { + return this.isInternalStore || this.config.forcePathStyle; + } + + private async files( + bucket: string = this.bucket, + external: boolean = false, + ): Promise { + const scope = `${external ? "external" : "internal"}:${bucket}`; + + const cached = this.clients.get(scope); + if (cached) { + return cached; + } + + const { Files, s3 } = await this.loadModules(); + + const client = new Files({ + adapter: s3({ + bucket, + endpoint: this.endpointFor(external), + region: this.config.region, + forcePathStyle: this.forcePathStyle, + credentials: this.credentials, + }), }); - this.externalClient = new Client({ - port: 443, - endPoint: process.env.DEMOS_DOMAIN, - useSSL: true, - accessKey: this.config.key, - secretKey: this.config.secret, + this.clients.set(scope, client); + + return client; + } + + // The multipart and object-version primitives below have no files-sdk + // equivalent -- it drives multipart uploads from its own process and has no + // way to hand a client a per-part signed URL, and its versioning plugin + // snapshots to a key prefix rather than using real S3 object versions. They + // talk to the AWS SDK directly rather than reaching through files.raw, which + // also keeps them clear of the ESM import. Unlike files(), the bucket is a + // per-command argument rather than baked into the client, so the endpoint is + // all that scopes these. + private raw(external: boolean = false): S3Client { + const scope = external ? "external" : "internal"; + + const cached = this.rawClients.get(scope); + if (cached) { + return cached; + } + + const client = new S3Client({ + endpoint: this.endpointFor(external), + region: this.config.region, + forcePathStyle: this.forcePathStyle, + credentials: this.credentials, }); + + this.rawClients.set(scope, client); + + return client; } - public get bucketName(): string { - return this.bucket; + public onModuleDestroy() { + for (const client of this.rawClients.values()) { + client.destroy(); + } + + this.rawClients.clear(); + this.clients.clear(); + } + + private static toObjectInfo(file: StoredFile): S3ObjectInfo { + return { + name: file.key, + size: file.size, + etag: file.etag, + lastModified: file.lastModified + ? new Date(file.lastModified) + : undefined, + }; } public multerStorage( @@ -52,7 +199,6 @@ export class S3Service { callback: (error?: string, file?: Express.Multer.File) => void, ) => { try { - // TODO - somehow we still leak memory await this.put(uploadPath(request, file), file.stream); request.file = file; @@ -77,23 +223,35 @@ export class S3Service { }; } - public async list(bucket: string = this.bucket): Promise { - return await this.client.listObjects(bucket).toArray(); + public async list(bucket: string = this.bucket): Promise { + const objects: S3ObjectInfo[] = []; + + for await (const object of this.listStream("", bucket)) { + objects.push(object); + } + + return objects; } - public listStream( + public async *listStream( prefix: string = "", - recursive: boolean = true, bucket: string = this.bucket, - ) { - return this.client.listObjects(bucket, prefix, recursive); + ): AsyncGenerator { + const client = await this.files(bucket); + + for await (const file of client.listAll({ prefix })) { + yield S3Service.toObjectInfo(file); + } } public async get( filename: string, bucket: string = this.bucket, ): Promise { - return await this.client.getObject(bucket, filename); + const client = await this.files(bucket); + const file = await client.download(filename, { as: "stream" }); + + return Readable.fromWeb(file.stream() as never); } public async getPartial( @@ -102,7 +260,17 @@ export class S3Service { length: number, bucket: string = this.bucket, ): Promise { - return await this.client.getPartialObject(bucket, filename, offset, length); + const client = await this.files(bucket); + + // files-sdk's range end is inclusive, so the last byte of a `length`-long + // window is offset + length - 1. Passing offset + length reads one byte + // too many. + const file = await client.download(filename, { + as: "stream", + range: { start: offset, end: offset + length - 1 }, + }); + + return Readable.fromWeb(file.stream() as never); } public async readPrefix( @@ -124,12 +292,20 @@ export class S3Service { contentType?: string, bucket: string = this.bucket, ): Promise { - await this.client.putObject( - bucket, + const client = await this.files(bucket); + + const isStream = stream instanceof Readable; + + await client.upload( filename, - stream, - undefined, - contentType ? { "Content-Type": contentType } : undefined, + isStream ? (Readable.toWeb(stream) as never) : stream, + { + ...(contentType ? { contentType } : {}), + // Demos and clips routinely run to hundreds of megabytes, and a stream + // body has no length to size a single PUT from. A buffer does, so it + // does not need to pay for multipart. + ...(isStream ? { multipart: true } : {}), + }, ); } @@ -138,40 +314,82 @@ export class S3Service { toKey: string, bucket: string = this.bucket, ): Promise { - await this.client.copyObject(bucket, toKey, `/${bucket}/${fromKey}`); + const client = await this.files(bucket); + await client.copy(fromKey, toKey); } - public async stat(filename: string, bucket: string = this.bucket) { - return await this.client.statObject(bucket, filename); + public async stat( + filename: string, + bucket: string = this.bucket, + ): Promise { + const client = await this.files(bucket); + const file = await client.head(filename); + + return { + size: file.size, + etag: file.etag, + lastModified: file.lastModified + ? new Date(file.lastModified) + : undefined, + metaData: { + ...file.metadata, + ...(file.type ? { "content-type": file.type } : {}), + }, + }; } public async removePrefix( prefix: string, bucket: string = this.bucket, ): Promise { - const entries: Array<{ name: string; versionId?: string }> = []; - const stream = this.client.listObjects(bucket, prefix, true, { - IncludeVersion: true, - }); + const client = this.raw(); - for await (const obj of stream) { - const info = obj as { name?: string; versionId?: string }; - if (!info.name) { - continue; - } - entries.push( - info.versionId && info.versionId !== "null" - ? { name: info.name, versionId: info.versionId } - : { name: info.name }, + let removed = 0; + let keyMarker: string | undefined; + let versionIdMarker: string | undefined; + + // Every version has to go, not just the current one: on a versioned bucket + // a plain delete only lays down a delete marker, and the objects it hides + // keep being billed forever. + do { + const listed = await client.send( + new ListObjectVersionsCommand({ + Bucket: bucket, + Prefix: prefix, + KeyMarker: keyMarker, + VersionIdMarker: versionIdMarker, + }), ); - } - let removed = 0; - for (let i = 0; i < entries.length; i += 1000) { - const batch = entries.slice(i, i + 1000); - await this.client.removeObjects(bucket, batch); - removed += batch.length; - } + const entries = [ + ...(listed.Versions ?? []), + ...(listed.DeleteMarkers ?? []), + ] + .filter((entry) => !!entry.Key) + .map((entry) => ({ + Key: entry.Key, + ...(entry.VersionId && entry.VersionId !== "null" + ? { VersionId: entry.VersionId } + : {}), + })); + + for (let i = 0; i < entries.length; i += 1000) { + const batch = entries.slice(i, i + 1000); + await client.send( + new DeleteObjectsCommand({ + Bucket: bucket, + Delete: { Objects: batch }, + }), + ); + removed += batch.length; + } + + keyMarker = listed.IsTruncated ? listed.NextKeyMarker : undefined; + versionIdMarker = listed.IsTruncated + ? listed.NextVersionIdMarker + : undefined; + } while (keyMarker || versionIdMarker); + return removed; } @@ -179,11 +397,24 @@ export class S3Service { keys: string[], bucket: string = this.bucket, ): Promise { + const client = await this.files(bucket); + let removed = 0; for (let i = 0; i < keys.length; i += 1000) { const batch = keys.slice(i, i + 1000); - await this.client.removeObjects(bucket, batch); - removed += batch.length; + + // The bulk delete resolves even when individual keys fail, collecting + // them in `errors` -- counting the batch instead of what came back + // reports a clean sweep over objects that are still there. + const result = await client.delete(batch); + + removed += result.deleted.length; + + for (const failure of result.errors ?? []) { + this.logger.error( + `unable to remove ${failure.key}: ${failure.error.message}`, + ); + } } return removed; } @@ -193,12 +424,10 @@ export class S3Service { bucket: string = this.bucket, ): Promise { try { - await this.client.removeObject(bucket, filename); + const client = await this.files(bucket); + await client.delete(filename); } catch (error) { - if (error.code === "NoSuchKey") { - return false; - } - this.logger.error("unable to remove", error.code); + this.logger.error("unable to remove", error.code ?? error.message); return false; } return true; @@ -208,14 +437,8 @@ export class S3Service { filepath: string, bucket: string = this.bucket, ): Promise { - try { - return !!(await this.client.statObject(bucket, filepath)); - } catch (error) { - if (error.code === "NotFound") { - return false; - } - throw error; - } + const client = await this.files(bucket); + return await client.exists(filepath); } public async getPresignedUrl( @@ -226,27 +449,36 @@ export class S3Service { type: "put" | "get" = "put", useLocal: boolean = false, ) { - let presignedUrl: string; - - const client = - !useLocal && this.config.endpoint === "minio" - ? this.externalClient - : this.client; + // A URL signed against the in-cluster Service name is unreachable from a + // browser or a game server node, so those are signed against the public + // demos domain instead. useLocal is for callers that read the object back + // from inside the cluster. + const external = !useLocal && this.isInternalStore; + const client = await this.files(bucket, external); if (type === "put") { - presignedUrl = await client.presignedPutObject(bucket, key, expires); - } else { - presignedUrl = await client.presignedGetObject(bucket, key, expires); + const upload = await client.signedUploadUrl(key, { expiresIn: expires }); + return upload.url; } - return presignedUrl; + return await client.url(key, { expiresIn: expires }); } public async createMultipartUpload( key: string, bucket: string = this.bucket, ): Promise { - return await this.client.initiateNewMultipartUpload(bucket, key, {}); + const client = this.raw(); + + const upload = await client.send( + new CreateMultipartUploadCommand({ Bucket: bucket, Key: key }), + ); + + if (!upload.UploadId) { + throw new Error(`no upload id returned for ${key}`); + } + + return upload.UploadId; } public async getPresignedPartUrl( @@ -256,13 +488,18 @@ export class S3Service { expires = 60 * 60 * 6, bucket: string = this.bucket, ): Promise { - const client = - this.config.endpoint === "minio" ? this.externalClient : this.client; - - return await client.presignedUrl("PUT", bucket, key, expires, { - uploadId, - partNumber: partNumber.toString(), - }); + const client = this.raw(this.isInternalStore); + + return await getSignedUrl( + client, + new UploadPartCommand({ + Bucket: bucket, + Key: key, + UploadId: uploadId, + PartNumber: partNumber, + }), + { expiresIn: expires }, + ); } public async completeMultipartUpload( @@ -270,25 +507,49 @@ export class S3Service { uploadId: string, bucket: string = this.bucket, ): Promise { - const parts = await ( - this.client as unknown as { - listParts: ( - bucket: string, - key: string, - uploadId: string, - ) => Promise>; - } - ).listParts(bucket, key, uploadId); + const client = this.raw(); + + // ListParts caps a page at 1000. Completing with a truncated part list + // does not error -- S3 assembles the object out of just those parts and + // silently drops the rest. + const parts: Array<{ PartNumber?: number; ETag?: string }> = []; + let partNumberMarker: string | undefined; + + do { + const listed = await client.send( + new ListPartsCommand({ + Bucket: bucket, + Key: key, + UploadId: uploadId, + PartNumberMarker: partNumberMarker, + }), + ); + + parts.push(...(listed.Parts ?? [])); + + partNumberMarker = listed.IsTruncated + ? listed.NextPartNumberMarker + : undefined; + } while (partNumberMarker); + if (parts.length === 0) { throw new Error("no parts uploaded"); } - await this.client.completeMultipartUpload( - bucket, - key, - uploadId, - parts - .sort((a, b) => a.part - b.part) - .map((part) => ({ part: part.part, etag: part.etag })), + + await client.send( + new CompleteMultipartUploadCommand({ + Bucket: bucket, + Key: key, + UploadId: uploadId, + MultipartUpload: { + Parts: parts + .sort((a, b) => a.PartNumber - b.PartNumber) + .map((part) => ({ + PartNumber: part.PartNumber, + ETag: part.ETag, + })), + }, + }), ); } @@ -297,6 +558,14 @@ export class S3Service { uploadId: string, bucket: string = this.bucket, ): Promise { - await this.client.abortMultipartUpload(bucket, key, uploadId); + const client = this.raw(); + + await client.send( + new AbortMultipartUploadCommand({ + Bucket: bucket, + Key: key, + UploadId: uploadId, + }), + ); } } diff --git a/src/system/system.service.spec.ts b/src/system/system.service.spec.ts index f99dd1942..43c05c9e7 100644 --- a/src/system/system.service.spec.ts +++ b/src/system/system.service.spec.ts @@ -87,12 +87,19 @@ describe("SystemService.parseImageRef", () => { describe("SystemService.isReservedDeployment", () => { // Plugin manifests are third-party input. If these names were claimable, a // plugin could get the panel to restart the panel. - it.each(["api", "web", "hasura", "panel", "redis", "timescaledb"])( - "reserves %s", - (name) => { - expect(SystemService.isReservedDeployment(name)).toBe(true); - }, - ); + it.each([ + "api", + "web", + "hasura", + "panel", + "redis", + "timescaledb", + "rustfs", + // minio outlives its own deployment as a Service alias. + "minio", + ])("reserves %s", (name) => { + expect(SystemService.isReservedDeployment(name)).toBe(true); + }); it.each(["inventory-frontend", "inventory-backend", "example-plugin"])( "allows %s", diff --git a/src/system/system.service.ts b/src/system/system.service.ts index b2af6c0b3..b573ee946 100644 --- a/src/system/system.service.ts +++ b/src/system/system.service.ts @@ -42,6 +42,9 @@ export class SystemService { "typesense", "timescaledb", "redis", + "rustfs", + // Still live after the RustFS migration: the panel keeps it as a Service + // alias onto the rustfs pods. "minio", "mediamtx", ]; diff --git a/yarn.lock b/yarn.lock index c074daacb..5f82c961e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -37,6 +37,262 @@ ora "5.4.1" rxjs "7.8.1" +"@aws-sdk/checksums@^3.1000.29": + version "3.1000.29" + resolved "https://registry.yarnpkg.com/@aws-sdk/checksums/-/checksums-3.1000.29.tgz#f12a6926eb3789057f5f16582fc226fe533c87fa" + integrity sha512-Dtu0gr4dnATZAPwEYbpCsG+MpLM7OAliy2gTepEFQwl1vZ6DL3QMH2FveMa3HLvPsOdhJsPRB3KtxVhph9T75A== + dependencies: + "@aws-sdk/core" "^3.977.9" + "@aws-sdk/types" "^3.974.5" + "@smithy/core" "^3.33.3" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@aws-sdk/client-s3@3.1125.0", "@aws-sdk/client-s3@^3.1125.0": + version "3.1125.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.1125.0.tgz#f95f92ec893daaa227486a40a82131a286586837" + integrity sha512-l0npObtjYgqDfUHiifnWGFuAuMVq5r4AVf4C+jY+thJ/2iAr/eHqAjBR4clbmXxSoJ5w3+ZFGRPyci/CCkUoyg== + dependencies: + "@aws-sdk/checksums" "^3.1000.29" + "@aws-sdk/core" "^3.977.9" + "@aws-sdk/credential-provider-node" "^3.972.82" + "@aws-sdk/middleware-sdk-s3" "^3.972.75" + "@aws-sdk/signature-v4-multi-region" "^3.996.46" + "@aws-sdk/types" "^3.974.5" + "@smithy/core" "^3.33.3" + "@smithy/fetch-http-handler" "^5.7.2" + "@smithy/node-http-handler" "^4.11.3" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@aws-sdk/core@^3.977.9": + version "3.977.9" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.977.9.tgz#c3d6b4bcce3df3c86831510f18bd2ce32172b136" + integrity sha512-reqPFEQrZxDZpeGj4PFMepBeR5LGYHRqq/L0motTzgFkCRBA4rFdaVXDSLYyGHhxVz7sT2PDnPN9CluGSfgyJA== + dependencies: + "@aws-sdk/types" "^3.974.5" + "@aws-sdk/xml-builder" "^3.972.40" + "@aws/lambda-invoke-store" "^0.3.0" + "@smithy/core" "^3.33.3" + "@smithy/signature-v4" "^5.6.12" + "@smithy/types" "^4.17.2" + bowser "^2.11.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-env@^3.972.70": + version "3.972.70" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.70.tgz#631ef02069bae65ac7d58c6878a09a42c24cb485" + integrity sha512-H404B7dJl2mCrBqahDEYsanB0xhdDp6tXnXcTUnXmmpy2Q3J0Ho0bUajZ2jr/RdwzCyS59Gi8xXIFwPLGBl6Uw== + dependencies: + "@aws-sdk/core" "^3.977.9" + "@aws-sdk/types" "^3.974.5" + "@smithy/core" "^3.33.3" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-http@^3.972.72": + version "3.972.72" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.72.tgz#9b737cc3879d900e703b219777e26d6bb542ffec" + integrity sha512-X98zYOrVOeuosCX+6ktf29FC2N2GHPLia7qv6mzPzTc+RPAuHWCDS++Z6JK7eGYqb/v6uaW7bAXaOvDBfol+0w== + dependencies: + "@aws-sdk/core" "^3.977.9" + "@aws-sdk/types" "^3.974.5" + "@smithy/core" "^3.33.3" + "@smithy/fetch-http-handler" "^5.7.2" + "@smithy/node-http-handler" "^4.11.3" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-ini@^3.973.15": + version "3.973.15" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.973.15.tgz#e185c40ba6b3eec90bf3cf7c364c79f639b15cca" + integrity sha512-Rykg6s5ceBuynMOGWgoowO4N+27JfnqXAnVaSunZl0hOO1XodSrxGNz6sCEbnmS0lAfQZDKyb3fbr46gSuv6Sg== + dependencies: + "@aws-sdk/core" "^3.977.9" + "@aws-sdk/credential-provider-env" "^3.972.70" + "@aws-sdk/credential-provider-http" "^3.972.72" + "@aws-sdk/credential-provider-login" "^3.972.77" + "@aws-sdk/credential-provider-process" "^3.972.70" + "@aws-sdk/credential-provider-sso" "^3.973.14" + "@aws-sdk/credential-provider-web-identity" "^3.972.76" + "@aws-sdk/nested-clients" "^3.997.44" + "@aws-sdk/types" "^3.974.5" + "@smithy/core" "^3.33.3" + "@smithy/credential-provider-imds" "^4.4.16" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-login@^3.972.77": + version "3.972.77" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.77.tgz#6ee6341077a6b920fc9322cfc37142a5b5bf2660" + integrity sha512-Jb59xfEISoN5mmbnA+HYqdtrSX3CgCtJoof+V5D8/TgUI56W63GEEd5Y58WijU3Ou6+WEgaLD1feVzaRXV5IDQ== + dependencies: + "@aws-sdk/core" "^3.977.9" + "@aws-sdk/nested-clients" "^3.997.44" + "@aws-sdk/types" "^3.974.5" + "@smithy/core" "^3.33.3" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-node@^3.972.82": + version "3.972.82" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.82.tgz#9967ea14f708f9e3274ed334a07a550282556a32" + integrity sha512-znDkEOGXB8W3kG1LJUKP3foBZY/9qLM0eil/DxWXSp37XsdsRLQHE/d/OaCGGVgKpA6znR38h/+INk8do1FjiA== + dependencies: + "@aws-sdk/credential-provider-env" "^3.972.70" + "@aws-sdk/credential-provider-http" "^3.972.72" + "@aws-sdk/credential-provider-ini" "^3.973.15" + "@aws-sdk/credential-provider-process" "^3.972.70" + "@aws-sdk/credential-provider-sso" "^3.973.14" + "@aws-sdk/credential-provider-web-identity" "^3.972.76" + "@aws-sdk/types" "^3.974.5" + "@smithy/core" "^3.33.3" + "@smithy/credential-provider-imds" "^4.4.16" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-process@^3.972.70": + version "3.972.70" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.70.tgz#ca9f5b334442e2ee04712840864563b89cdd5360" + integrity sha512-2ry03fGRJr4sV3jI+ocjj5JqALnFD6ymM5KiNCDZMvq8bX2GSbE0vji4aM43TVCl2nXqqLRZaUxdq/KeWRAY4Q== + dependencies: + "@aws-sdk/core" "^3.977.9" + "@aws-sdk/types" "^3.974.5" + "@smithy/core" "^3.33.3" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-sso@^3.973.14": + version "3.973.14" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.973.14.tgz#064acc04b4d0ef5ae879f2c2633a33c5a9238dda" + integrity sha512-jkhg/8ocAAoc0RFyLMhCw+/zZh7gystQgd4F4hznNa8P4Cc501PQmxd+jGLiMHodPJ+7Zv/3znM62gZojyasmA== + dependencies: + "@aws-sdk/core" "^3.977.9" + "@aws-sdk/nested-clients" "^3.997.44" + "@aws-sdk/token-providers" "3.1116.0" + "@aws-sdk/types" "^3.974.5" + "@smithy/core" "^3.33.3" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-web-identity@^3.972.76": + version "3.972.76" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.76.tgz#93a1913bfc7671008831cc80ba072470cba03bd1" + integrity sha512-d3AGyVu759PGr35mEB2s22xxlNEA5rpdxtSPJthfPFJvoQ8dt357iVPECqWfUxXp1toJAvKmbtcIYVGigaGsCA== + dependencies: + "@aws-sdk/core" "^3.977.9" + "@aws-sdk/nested-clients" "^3.997.44" + "@aws-sdk/types" "^3.974.5" + "@smithy/core" "^3.33.3" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@aws-sdk/lib-storage@^3.1125.0": + version "3.1125.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/lib-storage/-/lib-storage-3.1125.0.tgz#9562c664fa6b83ebf60b886088ed3a11811a2f03" + integrity sha512-/gSkxC34LojK0bKNDOg2kfcLGQlRiSSPwKnHVoD0IqeTa8huBMiF0YwQXsODYU0nWuT8HyK3FM+rXjZIreg6RA== + dependencies: + "@smithy/core" "^3.33.3" + "@smithy/types" "^4.17.2" + buffer "5.6.0" + events "3.3.0" + stream-browserify "3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-sdk-s3@^3.972.75": + version "3.972.75" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.75.tgz#d20222cbdd61197b245e0aaa3f79b7215dff31dc" + integrity sha512-wMIsNumRVKaNMKhvU/s9VrdEwE8S6gSzXp4RygFG5BEMnGkkXf8cjh8zf7cKJBpUDpqTWqwbz5isEgp9rH6Lng== + dependencies: + "@aws-sdk/core" "^3.977.9" + "@aws-sdk/signature-v4-multi-region" "^3.996.46" + "@aws-sdk/types" "^3.974.5" + "@smithy/core" "^3.33.3" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@aws-sdk/nested-clients@^3.997.44": + version "3.997.44" + resolved "https://registry.yarnpkg.com/@aws-sdk/nested-clients/-/nested-clients-3.997.44.tgz#ba02b5e0b12b57be425a7306a8c7b82f5eec4e0f" + integrity sha512-NhEgryjlBF9w38ZXqGymQV28IhkYa1mKhlbYnqIis57AYwWGVYfUPgg/qC2rLRqOUfblxx++irvju10kVTa8Vw== + dependencies: + "@aws-sdk/core" "^3.977.9" + "@aws-sdk/signature-v4-multi-region" "^3.996.46" + "@aws-sdk/types" "^3.974.5" + "@smithy/core" "^3.33.3" + "@smithy/fetch-http-handler" "^5.7.2" + "@smithy/node-http-handler" "^4.11.3" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@aws-sdk/s3-presigned-post@^3.1125.0": + version "3.1125.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/s3-presigned-post/-/s3-presigned-post-3.1125.0.tgz#89f7328b2c36fd84b9ce390edce391a68ca688b7" + integrity sha512-/nVyJ5xTBvbLuckWiZB1nCzMxt1bJMNppej3A7rliZdrdEbTYTLrciPX6twBv89K+cCCycyc+KkeK4nrEUBRlg== + dependencies: + "@aws-sdk/client-s3" "3.1125.0" + "@aws-sdk/core" "^3.977.9" + "@aws-sdk/types" "^3.974.5" + "@smithy/core" "^3.33.3" + "@smithy/signature-v4" "^5.6.12" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@aws-sdk/s3-request-presigner@^3.1125.0": + version "3.1125.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.1125.0.tgz#4c5a7f515eaf8ed575fd515ebeda58999c779527" + integrity sha512-WGK4s9XWk57ZvzfUw0j1m9xgKqCElZHVp5P80MQJCGV8A3Rpy2fAjDKrfauXQvBRHdECpijXpajpI/+X8Tsv+A== + dependencies: + "@aws-sdk/core" "^3.977.9" + "@aws-sdk/signature-v4-multi-region" "^3.996.46" + "@aws-sdk/types" "^3.974.5" + "@smithy/core" "^3.33.3" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@aws-sdk/signature-v4-multi-region@^3.996.46": + version "3.996.46" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.46.tgz#ee57afe5282da4b57968061ef8706d32890267ab" + integrity sha512-L+2xZTye/2T96f3lwCws0Zw6GG2JHZW9e8FpVgGBeeExSKyeoZ6CWRpBml/7DNiK/O26jrgPM9F+Ay8VkgzUWQ== + dependencies: + "@aws-sdk/types" "^3.974.5" + "@smithy/signature-v4" "^5.6.12" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@aws-sdk/token-providers@3.1116.0": + version "3.1116.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.1116.0.tgz#79c23d5cfeaf63f13a49f25035e8954083e09b6a" + integrity sha512-ygIivKqh8aHzNkucOCXHyIBgBpLPfrSI0mCqXF+vLBsPTUKqj0VSqAY0GFPe7lQl4HntjOcQ+KSyS7oUV2C54Q== + dependencies: + "@aws-sdk/core" "^3.977.9" + "@aws-sdk/nested-clients" "^3.997.44" + "@aws-sdk/types" "^3.974.5" + "@smithy/core" "^3.33.3" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@aws-sdk/types@^3.974.5": + version "3.974.5" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.974.5.tgz#a52691531738d191b8b3fd1ae7757c2eeec7afee" + integrity sha512-LkwLL2BLbC6wNNm4JaH9mbEqBMdOZCct6VAYqhdN4U1xrWM+fUJQEfbHwQgDypapOWTRtlk25akb5afM0P8CIQ== + dependencies: + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@aws-sdk/xml-builder@^3.972.40": + version "3.972.40" + resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.972.40.tgz#3cdb5f3400860ad91301aecb87fb5148a66d6ff7" + integrity sha512-wlFmCIGUlwF4zx/kncw+bmxTQh1HeSJq4mYV/V5cZUSJadDP3kXvGW8Rn21cimj/7y9ju+47oYWXi97vF7czaA== + dependencies: + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@aws/lambda-invoke-store@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@aws/lambda-invoke-store/-/lambda-invoke-store-0.3.0.tgz#708802d987f8e17bdf4af4de1031660ce1cdd65f" + integrity sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ== + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.27.1", "@babel/code-frame@^7.28.6", "@babel/code-frame@^7.29.0": version "7.29.0" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.29.0.tgz#7cd7a59f15b3cc0dcd803038f7792712a7d0b15c" @@ -676,6 +932,11 @@ protobufjs "^7.5.5" yargs "^17.7.2" +"@hono/node-server@^1.19.9 || ^2.0.5": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@hono/node-server/-/node-server-2.1.1.tgz#9cfa8649e9ecbcd48edf505b103002402ea51e70" + integrity sha512-ELuehkj5VCBdgEw9zs+ivkKwyzzUCSQuE96YmiPvn1ECBoZCczbFXJLeEGMTYjphP6gydh4pHMqEYPVMYUVgQg== + "@humanfs/core@^0.19.2": version "0.19.2" resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.2.tgz#a8272ca03b2acf492670222b2320b6c421bfde60" @@ -1341,6 +1602,29 @@ resolved "https://registry.yarnpkg.com/@mixmark-io/domino/-/domino-2.2.0.tgz#4e8ec69bf1afeb7a14f0628b7e2c0f35bdb336c3" integrity sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw== +"@modelcontextprotocol/sdk@^1.29.0": + version "1.30.0" + resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.30.0.tgz#dfa8a48347ec2d2c0d47917d7dc57f754e37f5ff" + integrity sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA== + dependencies: + "@hono/node-server" "^1.19.9 || ^2.0.5" + ajv "^8.17.1" + ajv-formats "^3.0.1" + content-type "^1.0.5" + cors "^2.8.5" + cross-spawn "^7.0.5" + eventsource "^3.0.2" + eventsource-parser "^3.0.0" + express "^5.2.1" + express-rate-limit "^8.2.1" + hono "^4.11.4" + jose "^6.1.3" + json-schema-typed "^8.0.2" + pkce-challenge "^5.0.0" + raw-body "^3.0.0" + zod "^3.25 || ^4.0" + zod-to-json-schema "^3.25.1" + "@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz#9edec61b22c3082018a79f6d1c30289ddf3d9d11" @@ -1525,11 +1809,6 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.8.0.tgz#cee43d801fcef9644b11b8194857695acd5f815a" integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== -"@nodable/entities@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@nodable/entities/-/entities-2.1.0.tgz#f543e5c6446720d4cf9e498a83019dd159973bc2" - integrity sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA== - "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1716,6 +1995,57 @@ dependencies: "@sinonjs/commons" "^3.0.1" +"@smithy/core@^3.33.2", "@smithy/core@^3.33.3": + version "3.33.3" + resolved "https://registry.yarnpkg.com/@smithy/core/-/core-3.33.3.tgz#c1e801fe17160bcbf6c714cf16e832057e6bf79e" + integrity sha512-CsOeKq/9kA3y6VJHt+/+VTCtBaxJ4OTFpgrjIUhPpDIKxBci1k2bJaQASF2h/ELWrulGp+t97DZ0mevfAD8idg== + dependencies: + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@smithy/credential-provider-imds@^4.4.16": + version "4.5.2" + resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-4.5.2.tgz#da3ea9636b5566b36b0761382d841a6d8fdde14f" + integrity sha512-A9uSdn72ozbRUSit0eib0TW7nXuNPlaeM0zcGkJ+nE6tFcSDbnmtwoxbTCFBukVQcszDAyvsd7+rTduPTXpygg== + dependencies: + "@smithy/core" "^3.33.2" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@smithy/fetch-http-handler@^5.7.2": + version "5.7.2" + resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-5.7.2.tgz#29e95cd74fe91495225e26a60569617fecae48cc" + integrity sha512-nZyWTmSpJEXl6VtWVMBJve/7x12DZu6sIX1z1a+ZMaHlQQRs9Zpu6NbTe/gmxYXVRpkjxyDYpZ5gx2IM6f/Wkw== + dependencies: + "@smithy/core" "^3.33.2" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@smithy/node-http-handler@^4.11.3": + version "4.12.0" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-4.12.0.tgz#3a45177c595bb832454f44e3c4eadd19f016bcde" + integrity sha512-0mq1pHadfyXCYCqm2cNpbjNIT+fbaUpNxewZb/YNr2L0IrEVMOb8gM/Fl4K6XvHCW3uSNDFwPl/+iKm0bx9jYg== + dependencies: + "@smithy/core" "^3.33.3" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@smithy/signature-v4@^5.6.12": + version "5.7.3" + resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-5.7.3.tgz#76603bf1ac9aa44e1d2f4f358b0cc0cf84961e46" + integrity sha512-7ImGm+FkHRLcBaRttIAMZ6bzJZWb2cJGoYjq46F2UjycujWzrL9GEN9h4w7eQyXJYnltrUhxbbieBAIRrdqpow== + dependencies: + "@smithy/core" "^3.33.3" + "@smithy/types" "^4.17.2" + tslib "^2.6.2" + +"@smithy/types@^4.17.2": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-4.17.2.tgz#ad71f6f62460a6409f0e8efc173e2e0f883ea4e6" + integrity sha512-FOKpVZob9MPTn2znRzGrnsMHv7BOsKVw3XiP/cOyYLDVZ9qKp4nifIiSCuUU/fIj5Vu0UOAxCFr+qRAtG0NUkA== + dependencies: + tslib "^2.6.2" + "@testcontainers/postgresql@^12.0.4": version "12.0.4" resolved "https://registry.yarnpkg.com/@testcontainers/postgresql/-/postgresql-12.0.4.tgz#251e05be35f128085d651f2e0c6ff68740c7f639" @@ -2598,7 +2928,7 @@ agent-base@^7.1.2: resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8" integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== -ajv-formats@3.0.1: +ajv-formats@3.0.1, ajv-formats@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-3.0.1.tgz#3d5dc762bca17679c3c2ea7e90ad6b7532309578" integrity sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ== @@ -2644,7 +2974,7 @@ ajv@^6.12.5, ajv@^6.14.0: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0, ajv@^8.9.0: +ajv@^8.0.0, ajv@^8.17.1, ajv@^8.9.0: version "8.20.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.20.0.tgz#304b3636add88ba7d936760dd50ece006dea95f9" integrity sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA== @@ -2808,6 +3138,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== +aws4fetch@^1.0.20: + version "1.0.20" + resolved "https://registry.yarnpkg.com/aws4fetch/-/aws4fetch-1.0.20.tgz#090d6c65e32c6df645dd5e5acf04cc56da575cbe" + integrity sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g== + axios@^1.6.0, axios@^1.8.4: version "1.15.2" resolved "https://registry.yarnpkg.com/axios/-/axios-1.15.2.tgz#eb8fb6d30349abace6ade5b4cb4d9e8a0dc23e5b" @@ -2935,7 +3270,7 @@ bare-url@^2.2.2: dependencies: bare-path "^3.0.0" -base64-js@^1.3.1: +base64-js@^1.0.2, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -2978,13 +3313,6 @@ bl@^4.0.3, bl@^4.1.0: inherits "^2.0.4" readable-stream "^3.4.0" -block-stream2@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/block-stream2/-/block-stream2-2.1.0.tgz#ac0c5ef4298b3857796e05be8ebed72196fa054b" - integrity sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg== - dependencies: - readable-stream "^3.4.0" - bn.js@^4.0.0: version "4.12.5" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.5.tgz#74f119ffecd823168d188eae06d97ea40835c489" @@ -3010,6 +3338,11 @@ boolbase@^1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== +bowser@^2.11.0: + version "2.14.1" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.14.1.tgz#4ea39bf31e305184522d7ad7bfd91389e4f0cb79" + integrity sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg== + brace-expansion@^1.1.7: version "1.1.14" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.14.tgz#d9de602370d91347cd9ddad1224d4fd701eb348b" @@ -3039,11 +3372,6 @@ braces@^3.0.3: dependencies: fill-range "^7.1.1" -browser-or-node@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/browser-or-node/-/browser-or-node-2.1.1.tgz#738790b3a86a8fc020193fa581273fbe65eaea0f" - integrity sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg== - browserslist@^4.24.0, browserslist@^4.28.1: version "4.28.2" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.2.tgz#f50b65362ef48974ca9f50b3680566d786b811d2" @@ -3084,6 +3412,14 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +buffer@5.6.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" + integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + buffer@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" @@ -3405,6 +3741,11 @@ commander@4.1.1: resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== +commander@^15.0.0: + version "15.0.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-15.0.0.tgz#96f3961f12adac1799ef3fbd8bc61d40572d1b11" + integrity sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg== + commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -3499,7 +3840,7 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -cors@2.8.6: +cors@2.8.6, cors@^2.8.5: version "2.8.6" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.6.tgz#ff5dd69bd95e547503820d29aba4f8faf8dfec96" integrity sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw== @@ -3550,7 +3891,7 @@ cron-parser@4.9.0: dependencies: luxon "^3.2.1" -cross-spawn@^7.0.3, cross-spawn@^7.0.6: +cross-spawn@^7.0.3, cross-spawn@^7.0.5, cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== @@ -3604,11 +3945,6 @@ decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== -decode-uri-component@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" - integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== - dedent@^1.6.0: version "1.7.2" resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.7.2.tgz#34e2264ab538301e27cf7b07bf2369c19baa8dd9" @@ -4087,11 +4423,23 @@ events-universal@^1.0.0: dependencies: bare-events "^2.7.0" -events@^3.2.0, events@^3.3.0: +events@3.3.0, events@^3.2.0, events@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== +eventsource-parser@^3.0.0, eventsource-parser@^3.0.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-3.1.1.tgz#b96cbb7dace4f3774f58a9e3b1ae9a4a524872e2" + integrity sha512-EKN1vKAMcZ8MlYMpaNuxN6R9yakzH6uajHcHVTqWJzvu5pWw9DyhbP35HH8MVBQ+dZjAfDxk+A8NiR9KWaXiyQ== + +eventsource@^3.0.2: + version "3.0.7" + resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-3.0.7.tgz#1157622e2f5377bb6aef2114372728ba0c156989" + integrity sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA== + dependencies: + eventsource-parser "^3.0.1" + execa@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -4124,6 +4472,14 @@ expect@30.3.0, expect@^30.0.0: jest-mock "30.3.0" jest-util "30.3.0" +express-rate-limit@^8.2.1: + version "8.7.0" + resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-8.7.0.tgz#87739a3535e7db3ca87b4a77b1ec5cc2c0a711e4" + integrity sha512-hOwV7WOxXfjRpAM1DSJWZDXx3GhplwD8IfwuwvogD8i1Qnkgosw/H45s4ZnFAUHDAhPjlY9hLBvJhKmGMyY26g== + dependencies: + debug "^4.4.3" + ip-address "^10.2.0" + express-session@^1.18.0: version "1.19.0" resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.19.0.tgz#682139f6eec6c69db9febbe2362e8a85dd84af2f" @@ -4218,23 +4574,6 @@ fast-uri@^3.0.1: resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa" integrity sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA== -fast-xml-builder@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/fast-xml-builder/-/fast-xml-builder-1.1.5.tgz#50188e1452a5fa095f415d3e63dcac0a1dbcbf11" - integrity sha512-4TJn/8FKLeslLAH3dnohXqE3QSoxkhvaMzepOIZytwJXZO69Bfz0HBdDHzOTOon6G59Zrk6VQ2bEiv1t61rfkA== - dependencies: - path-expression-matcher "^1.1.3" - -fast-xml-parser@^5.3.4: - version "5.7.2" - resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-5.7.2.tgz#fecd0b054c6c132fc03dab994a413da781e0eb9f" - integrity sha512-P7oW7tLbYnhOLQk/Gv7cZgzgMPP/XN03K02/Jy6Y/NHzyIAIpxuZIM/YqAkfiXFPxA2CTm7NtCijK9EDu09u2w== - dependencies: - "@nodable/entities" "^2.1.0" - fast-xml-builder "^1.1.5" - path-expression-matcher "^1.5.0" - strnum "^2.2.3" - fastq@^1.6.0: version "1.20.1" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.20.1.tgz#ca750a10dc925bc8b18839fd203e3ef4b3ced675" @@ -4254,6 +4593,11 @@ fdir@^6.5.0: resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== +fflate@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.3.tgz#bc27d8eb30343d4d512abb03480202ce65d825fc" + integrity sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA== + file-entry-cache@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" @@ -4278,6 +4622,21 @@ file-type@21.3.4: token-types "^6.1.1" uint8array-extras "^1.4.0" +files-sdk@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/files-sdk/-/files-sdk-2.3.0.tgz#18b8428c1fad823ce8a4fa0f2fe5df7c0c4f9bce" + integrity sha512-YOlRvcYPgrVf23Q7+E5rj7NTRwmym6VZG3vbr87HMS6jYluf2wd1zA9XCjJgtm1lTTmLzbJgs5UHLXl8CYOBJQ== + dependencies: + aws4fetch "^1.0.20" + commander "^15.0.0" + fflate "^0.8.3" + mime "^4.1.0" + p-map "^7.0.6" + picomatch "^4.0.5" + safe-regex2 "^5.1.1" + optionalDependencies: + "@modelcontextprotocol/sdk" "^1.29.0" + fill-range@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" @@ -4285,11 +4644,6 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" -filter-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" - integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ== - finalhandler@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-2.1.1.tgz#a2c517a6559852bcdb06d1f8bd7f51b68fad8099" @@ -4640,6 +4994,11 @@ hasown@^2.0.2: dependencies: function-bind "^1.1.2" +hono@^4.11.4: + version "4.13.5" + resolved "https://registry.yarnpkg.com/hono/-/hono-4.13.5.tgz#3df9463c4668a0321c39515309f5891e388e9709" + integrity sha512-O6+/eCYRkzzzy0rPWwKLiGBR1nFuUPZynnwjxN1MBA62NNqbT0wQEzQyK2gSO5yDIDB336sXQleAhOHrzlYyKw== + hookified@^1.15.0: version "1.15.1" resolved "https://registry.yarnpkg.com/hookified/-/hookified-1.15.1.tgz#b1fafeaa5489cdc29cb85546a8f837ed4ffbbcb6" @@ -4708,7 +5067,7 @@ iconv-lite@^0.7.0, iconv-lite@~0.7.0: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" -ieee754@^1.1.13, ieee754@^1.2.1: +ieee754@^1.1.13, ieee754@^1.1.4, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -4777,16 +5136,16 @@ ip-address@^10.1.1: resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-10.1.1.tgz#a7614252413e3751b841aaffba939090d2c4c37b" integrity sha512-1FMu8/N15Ck1BL551Jf42NYIoin2unWjLQ2Fze/DXryJRl5twqtwNHlO39qERGbIOcKYWHdgRryhOC+NG4eaLw== +ip-address@^10.2.0: + version "10.7.0" + resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-10.7.0.tgz#9713429f16787ede8f642f6255b41fb515c825d9" + integrity sha512-BGFsyJd5mpXp3rK6jIdADLNgpJUK1jnjzvYF8lK+VyDab9JAmqN0YOKDdP17HlgKb2+ehPgDc8EtnRLbGCAMhA== + ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== -ipaddr.js@^2.0.1: - version "2.3.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.3.0.tgz#71dce70e1398122208996d1c22f2ba46a24b1abc" - integrity sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg== - is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -5306,6 +5665,11 @@ jest@^30.0.3: import-local "^3.2.0" jest-cli "30.3.0" +jose@^6.1.3: + version "6.2.10" + resolved "https://registry.yarnpkg.com/jose/-/jose-6.2.10.tgz#b70436c920c4b3f97314c28a8b8612c15b1d9e7f" + integrity sha512-iiW7J9qRFlGxvCOIBDBDxFePQSn7ZMAnrYGhrrOo6siO/MIqwfyilLR27pkfDgUk+raLuzADS8A3S/KLBisc0g== + jose@^6.2.2: version "6.2.3" resolved "https://registry.yarnpkg.com/jose/-/jose-6.2.3.tgz#0975197ad973251221c658a3cddc4b951a250c2d" @@ -5361,6 +5725,11 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== +json-schema-typed@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/json-schema-typed/-/json-schema-typed-8.0.2.tgz#e98ee7b1899ff4a184534d1f167c288c66bbeff4" + integrity sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" @@ -5769,7 +6138,7 @@ mime-db@^1.54.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5" integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ== -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.35, mime-types@~2.1.24: +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.24: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -5788,6 +6157,11 @@ mime@2.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== +mime@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-4.1.0.tgz#ec55df7aa21832a36d44f0bbee5c04639b27802f" + integrity sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw== + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -5831,25 +6205,6 @@ minimist@^1.2.5, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -minio@^8.0.1: - version "8.0.7" - resolved "https://registry.yarnpkg.com/minio/-/minio-8.0.7.tgz#6a651151f3d2df1077ca894e46efc47f4a1ec25c" - integrity sha512-E737MgufW8CeQAsTAtnEMrxZ9scMSf29kkhZoXzDTKj/Jszzo2SfeZUH9wbDQH2Rsq6TCtl/yQL0+XdVKZansQ== - dependencies: - async "^3.2.4" - block-stream2 "^2.1.0" - browser-or-node "^2.1.1" - buffer-crc32 "^1.0.0" - eventemitter3 "^5.0.1" - fast-xml-parser "^5.3.4" - ipaddr.js "^2.0.1" - lodash "^4.17.21" - mime-types "^2.1.35" - query-string "^7.1.3" - stream-json "^1.8.0" - through2 "^4.0.2" - xml2js "^0.5.0 || ^0.6.2" - "minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2, minipass@^7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.3.tgz#79389b4eb1bb2d003a9bba87d492f2bd37bdc65b" @@ -6165,6 +6520,11 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" +p-map@^7.0.6: + version "7.0.7" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-7.0.7.tgz#a82175dd690468a930b9ae45c2b9829c5bf60fa3" + integrity sha512-VaWRu2i4FJNRtiRWCuuQRgfQ1B7a6+gMSrO+3j0EQi/k0ULfS9kosRxGoiqwzIjZTDI02tGfk5mXXltLg6QtfQ== + p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" @@ -6289,11 +6649,6 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== -path-expression-matcher@^1.1.3, path-expression-matcher@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz#3b98545dc88ffebb593e2d8458d0929da9275f4a" - integrity sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ== - path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -6418,11 +6773,21 @@ picomatch@^2.0.4, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.2.tgz#5a942915e26b372dc0f0e6753149a16e6b1c5601" integrity sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA== +picomatch@^4.0.5: + version "4.0.7" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.7.tgz#6313360034ccb36b3dc61ecbdff78121f90fe21f" + integrity sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA== + pirates@^4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.7.tgz#643b4a18c4257c8a65104b73f3049ce9a0a15e22" integrity sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA== +pkce-challenge@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/pkce-challenge/-/pkce-challenge-5.0.1.tgz#3b4446865b17b1745e9ace2016a31f48ddf6230d" + integrity sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ== + pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" @@ -6623,16 +6988,6 @@ qs@^6.1.0, qs@^6.11.0, qs@^6.14.0, qs@^6.14.1, qs@^6.5.2: dependencies: side-channel "^1.1.0" -query-string@^7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328" - integrity sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg== - dependencies: - decode-uri-component "^0.2.2" - filter-obj "^1.1.0" - split-on-first "^1.0.0" - strict-uri-encode "^2.0.0" - queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -6648,7 +7003,7 @@ range-parser@^1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@^3.0.1: +raw-body@^3.0.0, raw-body@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-3.0.2.tgz#3e3ada5ae5568f9095d84376fd3a49b8fb000a51" integrity sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA== @@ -6670,15 +7025,6 @@ react-is@^18.3.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== -readable-stream@3, readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - readable-stream@^2.0.5: version "2.3.8" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" @@ -6692,6 +7038,15 @@ readable-stream@^2.0.5: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readable-stream@^4.0.0: version "4.7.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.7.0.tgz#cedbd8a1146c13dfff8dab14068028d58c15ac91" @@ -6804,6 +7159,11 @@ restore-cursor@^4.0.0: onetime "^5.1.0" signal-exit "^3.0.2" +ret@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.5.0.tgz#30a4d38a7e704bd96dc5ffcbe7ce2a9274c41c95" + integrity sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw== + retry@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" @@ -6873,6 +7233,13 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +safe-regex2@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-regex2/-/safe-regex2-5.1.1.tgz#a5f3a6e35b8d84d0f41fa22efd5b6d30b367bbc7" + integrity sha512-mOSBvHGDZMuIEZMdOz/aCEYDCv0E7nfcNsIhUF+/P+xC7Hyf3FkvymqgPbg9D1EdSGu+uKbJgy09K/RKKc7kJA== + dependencies: + ret "~0.5.0" + "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -6891,11 +7258,6 @@ sanitize-html@^2.13.0: parse-srcset "^1.0.2" postcss "^8.3.11" -sax@>=0.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.6.0.tgz#da59637629307b97e7c4cb28e080a7bc38560d5b" - integrity sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA== - schema-utils@^3.1.1: version "3.3.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" @@ -7175,11 +7537,6 @@ split-ca@^1.0.1: resolved "https://registry.yarnpkg.com/split-ca/-/split-ca-1.0.1.tgz#6c83aff3692fa61256e0cd197e05e9de157691a6" integrity sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ== -split-on-first@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" - integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== - split2@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" @@ -7300,23 +7657,19 @@ steamid@^2.0.0: resolved "https://registry.yarnpkg.com/steamid/-/steamid-2.1.0.tgz#aa8cf11f21843aee63dead4903b1bd4f096df5c4" integrity sha512-ndt1cvuuSC+i8fcxVsmeyRlgGsR1QsoAuIXz+eabj8/Y4GIWE2+mgHA7Hys61JDHOxttfWtXHtN2m5TNYTlORg== +stream-browserify@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f" + integrity sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA== + dependencies: + inherits "~2.0.4" + readable-stream "^3.5.0" + stream-buffers@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-3.0.3.tgz#9fc6ae267d9c4df1190a781e011634cac58af3cd" integrity sha512-pqMqwQCso0PBJt2PQmDO0cFj0lyqmiwOMiMSkVtRokl7e+ZTRYgDHKnuZNbqjiJXgsg4nuqtD/zxuo9KqTp0Yw== -stream-chain@^2.2.5: - version "2.2.5" - resolved "https://registry.yarnpkg.com/stream-chain/-/stream-chain-2.2.5.tgz#b30967e8f14ee033c5b9a19bbe8a2cba90ba0d09" - integrity sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA== - -stream-json@^1.8.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/stream-json/-/stream-json-1.9.1.tgz#e3fec03e984a503718946c170db7d74556c2a187" - integrity sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw== - dependencies: - stream-chain "^2.2.5" - streamsearch@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" @@ -7331,11 +7684,6 @@ streamx@^2.12.5, streamx@^2.15.0, streamx@^2.25.0: fast-fifo "^1.3.2" text-decoder "^1.1.0" -strict-uri-encode@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" - integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ== - string-length@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -7426,11 +7774,6 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -strnum@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/strnum/-/strnum-2.2.3.tgz#0119fce02749a11bb126a4d686ac5dbdf6e57586" - integrity sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg== - strtok3@^10.3.4: version "10.3.5" resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-10.3.5.tgz#7213285da0dc3dec0fc8ce5df4b8b7a733f14360" @@ -7610,13 +7953,6 @@ text-decoder@^1.1.0: dependencies: b4a "^1.6.4" -through2@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/through2/-/through2-4.0.2.tgz#a7ce3ac2a7a8b0b966c80e7c49f0484c3b239764" - integrity sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw== - dependencies: - readable-stream "3" - tiny-typed-emitter@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz#b3b027fdd389ff81a152c8e847ee2f5be9fad7b5" @@ -8190,19 +8526,6 @@ ws@8.20.0, ws@^8.16.0, ws@^8.17.0, ws@^8.18.2: resolved "https://registry.yarnpkg.com/ws/-/ws-8.20.0.tgz#4cd9532358eba60bc863aad1623dfb045a4d4af8" integrity sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA== -"xml2js@^0.5.0 || ^0.6.2": - version "0.6.2" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" - integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== - dependencies: - sax ">=0.6.0" - xmlbuilder "~11.0.0" - -xmlbuilder@~11.0.0: - version "11.0.1" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" - integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== - xtend@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" @@ -8300,6 +8623,16 @@ zip-stream@^6.0.1: compress-commons "^6.0.2" readable-stream "^4.0.0" +zod-to-json-schema@^3.25.1: + version "3.25.2" + resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz#3fa799a7badd554541472fb65843fdc460b2e5aa" + integrity sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA== + +"zod@^3.25 || ^4.0": + version "4.5.4" + resolved "https://registry.yarnpkg.com/zod/-/zod-4.5.4.tgz#e215c62420c528dd7951e31fb52c5438f1fd184a" + integrity sha512-sC95tT5iHHH9gtpj6A81kh+NEaRAUFN+qlUPDUbRfOMvNf5QCBqsb3WgvnpVtK5Y+4UfA6KqufotuTvMGiTlsA== + zstddec@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/zstddec/-/zstddec-0.1.0.tgz#7050f3f0e0c3978562d0c566b3e5a427d2bad7ec"