diff --git a/apps/api/.env.example b/apps/api/.env.example index 66b04319..20fb2e11 100644 --- a/apps/api/.env.example +++ b/apps/api/.env.example @@ -9,6 +9,7 @@ DATABASE_URL= AGENTIC_WEB_BASE_URL= AGENTIC_GATEWAY_BASE_URL= +AGENTIC_STORAGE_BASE_URL='https://storage.agentic.so' JWT_SECRET= @@ -29,3 +30,11 @@ AGENTIC_ADMIN_API_KEY= # Used to simplify recreating the demo `@agentic/search` project during # development while we're frequently resetting the database AGENTIC_SEARCH_PROXY_SECRET= + +# s3 connection settings (compatible with cloudflare r2) +S3_BUCKET='agentic' +S3_REGION='auto' +# example: "https://.r2.cloudflarestorage.com" +S3_ENDPOINT= +S3_ACCESS_KEY_ID= +S3_ACCESS_KEY_SECRET= diff --git a/apps/api/package.json b/apps/api/package.json index 94d18795..e67f6cf4 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -25,7 +25,8 @@ "drizzle-kit:prod": "dotenvx run -o -f .env.production -- drizzle-kit", "clean": "del dist", "test": "run-s test:*", - "test:typecheck": "tsc --noEmit" + "test:typecheck": "tsc --noEmit", + "test:unit": "dotenvx run -- vitest run" }, "dependencies": { "@agentic/platform": "workspace:*", @@ -34,6 +35,8 @@ "@agentic/platform-hono": "workspace:*", "@agentic/platform-types": "workspace:*", "@agentic/platform-validators": "workspace:*", + "@aws-sdk/client-s3": "^3.840.0", + "@aws-sdk/s3-request-presigner": "^3.840.0", "@dicebear/collection": "catalog:", "@dicebear/core": "catalog:", "@fisch0920/drizzle-orm": "catalog:", diff --git a/apps/api/readme.md b/apps/api/readme.md new file mode 100644 index 00000000..19741aaa --- /dev/null +++ b/apps/api/readme.md @@ -0,0 +1,39 @@ +

+ + Agentic + +

+ +

+ Build Status + Prettier Code Formatting +

+ +# Agentic API + +> Backend API for the Agentic platform. + +- [Website](https://agentic.so) +- [Docs](https://docs.agentic.so) + +## Dependencies + +- **Postgres** + - `DATABASE_URL` - Postgres connection string + - [On macOS](https://wiki.postgresql.org/wiki/Homebrew): `brew install postgresql && brew services start postgresql` + - You'll need to run `pnpm drizzle-kit push` to set up your database schema +- **S3** - Required to use file attachments + - Any S3-compatible provider is supported, such as [Cloudflare R2](https://developers.cloudflare.com/r2/) + - Alterantively, you can use a local S3 server like [MinIO](https://github.com/minio/minio#homebrew-recommended) or [LocalStack](https://github.com/localstack/localstack) + - To run LocalStack on macOS: `brew install localstack/tap/localstack-cli && localstack start -d` + - To run MinIO macOS: `brew install minio/stable/minio && minio server /data` + - I recommend using Cloudflare R2, though – it's amazing and should be free for most use cases! + - `S3_BUCKET` - Required + - `S3_REGION` - Optional; defaults to `auto` + - `S3_ENDPOINT` - Required; example: `https://.r2.cloudflarestorage.com` + - `ACCESS_KEY_ID` - Required ([cloudflare R2 docs](https://developers.cloudflare.com/r2/api/s3/tokens/)) + - `SECRET_ACCESS_KEY` - Required ([cloudflare R2 docs](https://developers.cloudflare.com/r2/api/s3/tokens/)) + +## License + +[GNU AGPL 3.0](https://choosealicense.com/licenses/agpl-3.0/) diff --git a/apps/api/src/api-v1/auth/github-init.ts b/apps/api/src/api-v1/auth/github-init.ts index 7933984d..c5c0b76b 100644 --- a/apps/api/src/api-v1/auth/github-init.ts +++ b/apps/api/src/api-v1/auth/github-init.ts @@ -48,7 +48,8 @@ export function registerV1GitHubOAuthInitFlow( const state = crypto.randomUUID() - // TODO: unique identifier + // TODO: unique identifier! + // TODO: THIS IS IMPORTANT!! if multiple users are authenticating with github concurrently, this will currently really mess things up... await authStorage.set(['github', state, 'redirectUri'], { redirectUri }) const publicRedirectUri = `${env.apiBaseUrl}/v1/auth/github/callback` diff --git a/apps/api/src/api-v1/auth/utils.ts b/apps/api/src/api-v1/auth/utils.ts index c8926e21..e1ee1f70 100644 --- a/apps/api/src/api-v1/auth/utils.ts +++ b/apps/api/src/api-v1/auth/utils.ts @@ -1,3 +1,3 @@ -import { DrizzleAuthStorage } from '@/lib/drizzle-auth-storage' +import { DrizzleAuthStorage } from '@/lib/auth/drizzle-auth-storage' export const authStorage = DrizzleAuthStorage() diff --git a/apps/api/src/api-v1/index.ts b/apps/api/src/api-v1/index.ts index a5061ce5..831f397a 100644 --- a/apps/api/src/api-v1/index.ts +++ b/apps/api/src/api-v1/index.ts @@ -39,6 +39,7 @@ import { registerV1GetPublicProjectByIdentifier } from './projects/get-public-pr import { registerV1ListProjects } from './projects/list-projects' import { registerV1ListPublicProjects } from './projects/list-public-projects' import { registerV1UpdateProject } from './projects/update-project' +import { registerV1GetSignedStorageUploadUrl } from './storage/get-signed-storage-upload-url' import { registerV1CreateTeam } from './teams/create-team' import { registerV1DeleteTeam } from './teams/delete-team' import { registerV1GetTeam } from './teams/get-team' @@ -95,6 +96,9 @@ registerV1CreateTeamMember(privateRouter) registerV1UpdateTeamMember(privateRouter) registerV1DeleteTeamMember(privateRouter) +// Storage +registerV1GetSignedStorageUploadUrl(privateRouter) + // Public projects registerV1ListPublicProjects(publicRouter) registerV1GetPublicProjectByIdentifier(publicRouter) // must be before `registerV1GetPublicProject` diff --git a/apps/api/src/api-v1/storage/get-signed-storage-upload-url.ts b/apps/api/src/api-v1/storage/get-signed-storage-upload-url.ts new file mode 100644 index 00000000..ba0c4257 --- /dev/null +++ b/apps/api/src/api-v1/storage/get-signed-storage-upload-url.ts @@ -0,0 +1,86 @@ +import { assert } from '@agentic/platform-core' +import { createRoute, type OpenAPIHono, z } from '@hono/zod-openapi' + +import type { AuthenticatedHonoEnv } from '@/lib/types' +import { db, eq, projectIdentifierSchema, schema } from '@/db' +import { acl } from '@/lib/acl' +import { + openapiAuthenticatedSecuritySchemas, + openapiErrorResponse404, + openapiErrorResponses +} from '@/lib/openapi-utils' +import { + getStorageObjectPublicUrl, + getStorageSignedUploadUrl +} from '@/lib/storage' + +export const getSignedUploadUrlQuerySchema = z.object({ + projectIdentifier: projectIdentifierSchema, + + /** + * Should be a hash of the contents of the file to upload with the correct + * file extension. + * + * @example `9f86d081884c7d659a2feaa0c55ad015a.png` + */ + key: z + .string() + .nonempty() + .describe( + 'Should be a hash of the contents of the file to upload with the correct file extension (eg, "9f86d081884c7d659a2feaa0c55ad015a.png").' + ) +}) + +const route = createRoute({ + description: + "Gets a signed URL for uploading a file to Agentic's blob storage. Files are namespaced to a given project and are identified by a key that should be a hash of the file's contents, with the correct file extension.", + tags: ['storage'], + operationId: 'getSignedStorageUploadUrl', + method: 'get', + path: 'storage/signed-upload-url', + security: openapiAuthenticatedSecuritySchemas, + request: { + query: getSignedUploadUrlQuerySchema + }, + responses: { + 200: { + description: 'A signed upload URL', + content: { + 'application/json': { + schema: z.object({ + signedUploadUrl: z + .string() + .url() + .describe('The signed upload URL.'), + publicObjectUrl: z + .string() + .url() + .describe('The public URL the object will have once uploaded.') + }) + } + } + }, + ...openapiErrorResponses, + ...openapiErrorResponse404 + } +}) + +export function registerV1GetSignedStorageUploadUrl( + app: OpenAPIHono +) { + return app.openapi(route, async (c) => { + const { projectIdentifier, key } = c.req.valid('query') + + const project = await db.query.projects.findFirst({ + where: eq(schema.projects.identifier, projectIdentifier) + }) + assert(project, 404, `Project not found "${projectIdentifier}"`) + await acl(c, project, { label: 'Project' }) + + const compoundKey = `${project.identifier}/${key}` + const signedUploadUrl = await getStorageSignedUploadUrl(compoundKey) + const publicObjectUrl = getStorageObjectPublicUrl(compoundKey) + + return c.json({ signedUploadUrl, publicObjectUrl }) + }) +} diff --git a/apps/api/src/lib/auth/auth-storage.ts b/apps/api/src/lib/auth/auth-storage.ts new file mode 100644 index 00000000..ab1b4c4b --- /dev/null +++ b/apps/api/src/lib/auth/auth-storage.ts @@ -0,0 +1,46 @@ +export interface AuthStorageAdapter { + get(key: string[]): Promise | undefined> + remove(key: string[]): Promise + set(key: string[], value: any, expiry?: Date): Promise + scan(prefix: string[]): AsyncIterable<[string[], any]> +} + +const SEPERATOR = String.fromCodePoint(0x1f) + +export function joinKey(key: string[]) { + return key.join(SEPERATOR) +} + +export function splitKey(key: string) { + return key.split(SEPERATOR) +} + +export namespace AuthStorage { + function encode(key: string[]) { + return key.map((k) => k.replaceAll(SEPERATOR, '')) + } + export function get(adapter: AuthStorageAdapter, key: string[]) { + return adapter.get(encode(key)) as Promise + } + + export function set( + adapter: AuthStorageAdapter, + key: string[], + value: any, + ttl?: number + ) { + const expiry = ttl ? new Date(Date.now() + ttl * 1000) : undefined + return adapter.set(encode(key), value, expiry) + } + + export function remove(adapter: AuthStorageAdapter, key: string[]) { + return adapter.remove(encode(key)) + } + + export function scan( + adapter: AuthStorageAdapter, + key: string[] + ): AsyncIterable<[string[], T]> { + return adapter.scan(encode(key)) + } +} diff --git a/apps/api/src/lib/drizzle-auth-storage.ts b/apps/api/src/lib/auth/drizzle-auth-storage.ts similarity index 91% rename from apps/api/src/lib/drizzle-auth-storage.ts rename to apps/api/src/lib/auth/drizzle-auth-storage.ts index f129faf6..89887066 100644 --- a/apps/api/src/lib/drizzle-auth-storage.ts +++ b/apps/api/src/lib/auth/drizzle-auth-storage.ts @@ -1,7 +1,8 @@ import { and, db, eq, gt, isNull, like, or, schema } from '@/db' -import { joinKey, splitKey, type StorageAdapter } from '@/lib/storage' -export function DrizzleAuthStorage(): StorageAdapter { +import { type AuthStorageAdapter, joinKey, splitKey } from './auth-storage' + +export function DrizzleAuthStorage(): AuthStorageAdapter { return { async get(key: string[]) { const id = joinKey(key) diff --git a/apps/api/src/lib/env.ts b/apps/api/src/lib/env.ts index 3709a754..f457c4a6 100644 --- a/apps/api/src/lib/env.ts +++ b/apps/api/src/lib/env.ts @@ -12,6 +12,11 @@ export const envSchema = baseEnvSchema AGENTIC_WEB_BASE_URL: z.string().url(), AGENTIC_GATEWAY_BASE_URL: z.string().url(), + AGENTIC_STORAGE_BASE_URL: z + .string() + .url() + .optional() + .default('https://storage.agentic.so'), JWT_SECRET: z.string().nonempty(), @@ -30,7 +35,13 @@ export const envSchema = baseEnvSchema // Used to simplify recreating the demo `@agentic/search` project during // development while we're frequently resetting the database - AGENTIC_SEARCH_PROXY_SECRET: z.string().nonempty() + AGENTIC_SEARCH_PROXY_SECRET: z.string().nonempty(), + + S3_BUCKET: z.string().nonempty().optional().default('agentic'), + S3_REGION: z.string().nonempty().optional().default('auto'), + S3_ENDPOINT: z.string().nonempty().url(), + S3_ACCESS_KEY_ID: z.string().nonempty(), + S3_ACCESS_KEY_SECRET: z.string().nonempty() }) .strip() export type RawEnv = z.infer diff --git a/apps/api/src/lib/storage.test.ts b/apps/api/src/lib/storage.test.ts new file mode 100644 index 00000000..a22432bb --- /dev/null +++ b/apps/api/src/lib/storage.test.ts @@ -0,0 +1,30 @@ +import { describe, expect, it } from 'vitest' + +import { + deleteStorageObject, + getStorageObject, + putStorageObject +} from './storage' + +describe('Storage', () => { + it('putObject, getObject, deleteObject', async () => { + if (!process.env.ACCESS_KEY_ID) { + // TODO: ignore on CI + expect(true).toEqual(true) + return + } + + await putStorageObject('test.txt', 'hello world', { + ContentType: 'text/plain' + }) + + const obj = await getStorageObject('test.txt') + expect(obj.ContentType).toEqual('text/plain') + + const body = await obj.Body?.transformToString() + expect(body).toEqual('hello world') + + const res = await deleteStorageObject('test.txt') + expect(res.$metadata.httpStatusCode).toEqual(204) + }) +}) diff --git a/apps/api/src/lib/storage.ts b/apps/api/src/lib/storage.ts index 33d59d46..f52debfc 100644 --- a/apps/api/src/lib/storage.ts +++ b/apps/api/src/lib/storage.ts @@ -1,46 +1,91 @@ -export interface StorageAdapter { - get(key: string[]): Promise | undefined> - remove(key: string[]): Promise - set(key: string[], value: any, expiry?: Date): Promise - scan(prefix: string[]): AsyncIterable<[string[], any]> +import { + DeleteObjectCommand, + type DeleteObjectCommandInput, + GetObjectCommand, + type GetObjectCommandInput, + PutObjectCommand, + type PutObjectCommandInput, + S3Client +} from '@aws-sdk/client-s3' +import { getSignedUrl } from '@aws-sdk/s3-request-presigner' + +import { env } from './env' + +// This storage client is designed to work with any S3-compatible storage provider. +// For Cloudflare R2, see https://developers.cloudflare.com/r2/examples/aws/aws-sdk-js-v3/ + +const Bucket = env.S3_BUCKET + +export const storageClient = new S3Client({ + region: env.S3_REGION, + endpoint: env.S3_ENDPOINT, + credentials: { + accessKeyId: env.S3_ACCESS_KEY_ID, + secretAccessKey: env.S3_ACCESS_KEY_SECRET + } +}) + +// This ensures that buckets are created automatically if they don't exist on +// Cloudflare R2. It won't affect other providers. +// @see https://developers.cloudflare.com/r2/examples/aws/custom-header/ +storageClient.middlewareStack.add( + (next, _) => async (args) => { + const r = args.request as RequestInit + r.headers = { + 'cf-create-bucket-if-missing': 'true', + ...r.headers + } + + return next(args) + }, + { step: 'build', name: 'customHeaders' } +) + +export async function getStorageObject( + key: string, + opts?: Omit +) { + return storageClient.send(new GetObjectCommand({ Bucket, Key: key, ...opts })) } -const SEPERATOR = String.fromCodePoint(0x1f) - -export function joinKey(key: string[]) { - return key.join(SEPERATOR) +export async function putStorageObject( + key: string, + value: PutObjectCommandInput['Body'], + opts?: Omit +) { + return storageClient.send( + new PutObjectCommand({ Bucket, Key: key, Body: value, ...opts }) + ) } -export function splitKey(key: string) { - return key.split(SEPERATOR) +export async function deleteStorageObject( + key: string, + opts?: Omit +) { + return storageClient.send( + new DeleteObjectCommand({ Bucket, Key: key, ...opts }) + ) } -export namespace Storage { - function encode(key: string[]) { - return key.map((k) => k.replaceAll(SEPERATOR, '')) - } - export function get(adapter: StorageAdapter, key: string[]) { - return adapter.get(encode(key)) as Promise - } - - export function set( - adapter: StorageAdapter, - key: string[], - value: any, - ttl?: number - ) { - const expiry = ttl ? new Date(Date.now() + ttl * 1000) : undefined - return adapter.set(encode(key), value, expiry) - } - - export function remove(adapter: StorageAdapter, key: string[]) { - return adapter.remove(encode(key)) - } - - export function scan( - adapter: StorageAdapter, - key: string[] - ): AsyncIterable<[string[], T]> { - return adapter.scan(encode(key)) - } +export function getStorageObjectInternalUrl(key: string) { + return `${env.AGENTIC_STORAGE_BASE_URL}/${Bucket}/${key}` +} + +export function getStorageObjectPublicUrl(key: string) { + return `${env.AGENTIC_STORAGE_BASE_URL}/${key}` +} + +export async function getStorageSignedUploadUrl( + key: string, + { + expiresIn = 5 * 60 * 1000 // 5 minutes + }: { + expiresIn?: number + } = {} +) { + return getSignedUrl( + storageClient, + new PutObjectCommand({ Bucket, Key: key }), + { expiresIn } + ) } diff --git a/apps/api/src/openauth-temp b/apps/api/src/openauth-temp deleted file mode 100644 index b67b0987..00000000 --- a/apps/api/src/openauth-temp +++ /dev/null @@ -1,145 +0,0 @@ -import { issuer } from '@agentic/openauth' -import { GithubProvider } from '@agentic/openauth/provider/github' -import { PasswordProvider } from '@agentic/openauth/provider/password' -import { assert, pick } from '@agentic/platform-core' -import { isValidPassword } from '@agentic/platform-validators' - -import { type RawUser } from '@/db' -import { subjects } from '@/lib/auth/subjects' -import { upsertOrLinkUserAccount } from '@/lib/auth/upsert-or-link-user-account' -import { DrizzleAuthStorage } from '@/lib/drizzle-auth-storage' -import { env } from '@/lib/env' -import { getGitHubClient } from '@/lib/external/github' - -import { resend } from './lib/external/resend' - -// Initialize OpenAuth issuer which is a Hono app for all auth routes. -// TODO: fix this type... -export const authRouter: any = issuer({ - subjects, - storage: DrizzleAuthStorage(), - ttl: { - access: 60 * 60 * 24 * 30, // 30 days - refresh: 60 * 60 * 24 * 365 // 1 year - // Used for creating longer-lived tokens for testing - // access: 60 * 60 * 24 * 366, // 1 year - // refresh: 60 * 60 * 24 * 365 * 5 // 5 years - }, - providers: { - github: GithubProvider({ - clientID: env.GITHUB_CLIENT_ID, - clientSecret: env.GITHUB_CLIENT_SECRET, - scopes: ['user:email'] - }), - password: PasswordProvider({ - loginUrl: async () => `${env.WEB_AUTH_BASE_URL}/login`, - registerUrl: async () => `${env.WEB_AUTH_BASE_URL}/signup`, - changeUrl: async () => `${env.WEB_AUTH_BASE_URL}/forgot-password`, - sendCode: async (email, code) => { - // eslint-disable-next-line no-console - console.log('sending verify code email', { email, code }) - - await resend.sendVerifyCodeEmail({ code, to: email }) - }, - validatePassword: (password) => { - if (password.length < 3) { - return 'Password must be at least 3 characters' - } - - if (password.length > 1024) { - return 'Password must be less than 1024 characters' - } - - if (!isValidPassword(password)) { - return 'Invalid password' - } - - return undefined - } - }) - }, - success: async (ctx, value) => { - const { provider } = value - let user: RawUser | undefined - - // eslint-disable-next-line no-console - console.log('Auth success', provider, JSON.stringify(value, null, 2)) - - function getPartialOAuthAccount() { - assert(provider === 'github', `Unsupported OAuth provider "${provider}"`) - const now = Date.now() - - return { - provider, - accessToken: value.tokenset.access, - refreshToken: value.tokenset.refresh, - // `expires_in` and `refresh_token_expires_in` are given in seconds - accessTokenExpiresAt: new Date( - now + value.tokenset.raw.expires_in * 1000 - ), - refreshTokenExpiresAt: new Date( - now + value.tokenset.raw.refresh_token_expires_in * 1000 - ), - scope: (value.tokenset.raw.scope as string) || undefined - } - } - - if (provider === 'github') { - const client = getGitHubClient({ accessToken: value.tokenset.access }) - const { data: ghUser } = await client.rest.users.getAuthenticated() - - if (!ghUser.email) { - const { data: emails } = await client.request('GET /user/emails') - const primary = emails.find((e) => e.primary) - const verified = emails.find((e) => e.verified) - const fallback = emails.find((e) => e.email) - const email = primary?.email || verified?.email || fallback?.email - ghUser.email = email! - } - - assert( - ghUser.email, - 'Error authenticating with GitHub: user email is required.' - ) - - user = await upsertOrLinkUserAccount({ - partialAccount: { - accountId: `${ghUser.id}`, - accountUsername: ghUser.login.toLowerCase(), - ...getPartialOAuthAccount() - }, - partialUser: { - email: ghUser.email, - isEmailVerified: true, - name: ghUser.name || undefined, - username: ghUser.login.toLowerCase(), - image: ghUser.avatar_url - } - }) - } else if (provider === 'password') { - user = await upsertOrLinkUserAccount({ - partialAccount: { - provider, - accountId: value.email - }, - partialUser: { - email: value.email, - isEmailVerified: true - } - }) - } else { - assert( - user, - 400, - `Authentication error: unsupported auth provider "${provider}"` - ) - } - - assert( - user, - 500, - `Authentication error for auth provider "${provider}": Unexpected error initializing user` - ) - return ctx.subject('user', pick(user, 'id', 'username')) - } -}) diff --git a/packages/api-client/package.json b/packages/api-client/package.json index 0ce144a1..67bb4a13 100644 --- a/packages/api-client/package.json +++ b/packages/api-client/package.json @@ -29,6 +29,7 @@ "@agentic/platform-core": "workspace:*", "@agentic/platform-types": "workspace:*", "@standard-schema/spec": "catalog:", + "file-type": "^21.0.0", "ky": "catalog:", "type-fest": "catalog:" }, diff --git a/packages/api-client/src/agentic-api-client.ts b/packages/api-client/src/agentic-api-client.ts index eed4a819..ff28a00a 100644 --- a/packages/api-client/src/agentic-api-client.ts +++ b/packages/api-client/src/agentic-api-client.ts @@ -11,7 +11,8 @@ import type { User } from '@agentic/platform-types' import type { Simplify } from 'type-fest' -import { assert, sanitizeSearchParams } from '@agentic/platform-core' +import { assert, sanitizeSearchParams, sha256 } from '@agentic/platform-core' +import { fileTypeFromBuffer } from 'file-type' import defaultKy, { type KyInstance } from 'ky' import type { OnUpdateAuthSessionFunction } from './types' @@ -336,6 +337,103 @@ export class AgenticApiClient { .json() } + /** + * Gets a signed URL for uploading a file to Agentic's blob storage. + * + * Files are namespaced to a given project and are identified by a key that + * should be a hash of the file's contents, with the correct file extension. + * + * @example + * ```ts + * const { signedUploadUrl, publicObjectUrl } = await client.getSignedStorageUploadUrl({ + * projectIdentifier: '@username/my-project', + * key: '9f86d081884c7d659a2feaa0c55ad015a.png' + * }) + * ``` + */ + async getSignedStorageUploadUrl( + searchParams: OperationParameters<'getSignedStorageUploadUrl'> + ): Promise<{ + /** The signed upload URL. */ + signedUploadUrl: string + + /** The public URL the object will have once uploaded. */ + publicObjectUrl: string + }> { + return this.ky + .get(`v1/storage/signed-upload-url`, { + searchParams: sanitizeSearchParams(searchParams) + }) + .json() + } + + /** + * Uploads a file to Agentic's blob storage for a given project. + * + * @example + * ```ts + * const publicObjectUrl = await client.uploadFileToStorage( + * new URL('https://example.com/image.png'), + * { projectIdentifier: '@username/my-project' } + * ) + * ``` + */ + async uploadFileToStorage( + source: string | ArrayBuffer | URL, + { + projectIdentifier + }: { + projectIdentifier: string + } + ): Promise { + let sourceBuffer: ArrayBuffer + + if (typeof source === 'string') { + try { + source = new URL(source) + } catch { + // Not a URL + throw new Error(`Invalid source file URL: ${source}`) + } + } + + if (source instanceof URL) { + sourceBuffer = await defaultKy.get(source).arrayBuffer() + } else if (source instanceof ArrayBuffer) { + sourceBuffer = source + } else { + throw new Error(`Invalid source file: ${source}`) + } + + const [hash, fileType] = await Promise.all([ + sha256(sourceBuffer), + fileTypeFromBuffer(sourceBuffer) + ]) + + const key = fileType ? `${hash}.${fileType.ext}` : hash + + const { signedUploadUrl, publicObjectUrl } = + await this.getSignedStorageUploadUrl({ + projectIdentifier, + key + }) + + try { + // Check if the object already exists. + await defaultKy.head(publicObjectUrl) + } catch { + // Object doesn't exist yet, so upload it. + await defaultKy.post(signedUploadUrl, { + body: sourceBuffer, + headers: { + 'Content-Type': fileType?.mime ?? 'application/octet-stream' + } + }) + } + + return publicObjectUrl + } + /** Lists projects that have been published publicly to the marketplace. */ async listPublicProjects< TPopulate extends NonNullable< diff --git a/packages/types/src/openapi.d.ts b/packages/types/src/openapi.d.ts index 4f9257d8..09771634 100644 --- a/packages/types/src/openapi.d.ts +++ b/packages/types/src/openapi.d.ts @@ -247,6 +247,23 @@ export interface paths { patch?: never; trace?: never; }; + "/v1/storage/signed-upload-url": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** @description Gets a signed URL for uploading a file to Agentic's blob storage. Files are namespaced to a given project and are identified by a key that should be a hash of the file's contents, with the correct file extension. */ + get: operations["getSignedStorageUploadUrl"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/v1/projects": { parameters: { query?: never; @@ -1811,6 +1828,46 @@ export interface operations { 404: components["responses"]["404"]; }; }; + getSignedStorageUploadUrl: { + parameters: { + query: { + /** @description Public project identifier (e.g. "@namespace/project-slug") */ + projectIdentifier: components["schemas"]["ProjectIdentifier"]; + /** @description Should be a hash of the contents of the file to upload with the correct file extension (eg, "9f86d081884c7d659a2feaa0c55ad015a.png"). */ + key: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description A signed upload URL */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** + * Format: uri + * @description The signed upload URL. + */ + signedUploadUrl: string; + /** + * Format: uri + * @description The public URL the object will have once uploaded. + */ + publicObjectUrl: string; + }; + }; + }; + 400: components["responses"]["400"]; + 401: components["responses"]["401"]; + 403: components["responses"]["403"]; + 404: components["responses"]["404"]; + }; + }; listProjects: { parameters: { query?: { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bfdd2a39..f6a5ef57 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -581,6 +581,12 @@ importers: '@agentic/platform-validators': specifier: workspace:* version: link:../../packages/validators + '@aws-sdk/client-s3': + specifier: ^3.840.0 + version: 3.840.0 + '@aws-sdk/s3-request-presigner': + specifier: ^3.840.0 + version: 3.840.0 '@dicebear/collection': specifier: 'catalog:' version: 9.2.3(@dicebear/core@9.2.3) @@ -1166,6 +1172,9 @@ importers: '@standard-schema/spec': specifier: 'catalog:' version: 1.0.0 + file-type: + specifier: ^21.0.0 + version: 21.0.0 ky: specifier: 'catalog:' version: 1.8.1 @@ -1696,6 +1705,16 @@ packages: '@aws-crypto/crc32@3.0.0': resolution: {integrity: sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==} + '@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==} @@ -1716,6 +1735,10 @@ packages: resolution: {integrity: sha512-Pq/A5W46Z0JrRTIl4eVvguQjXWwVHiiBC3WyrLxlIH0hMS6bILgC7H+z+JiCm4mXR/oF2ZobQ8Wei/Sga1Uxkw==} engines: {node: '>=18.0.0'} + '@aws-sdk/client-s3@3.840.0': + resolution: {integrity: sha512-dRuo03EqGBbl9+PTogpwY9bYmGWIjn8nB82HN5Qj20otgjUvhLOdEkkip9mroYsrvqNoKbMedWdCudIcB/YY1w==} + engines: {node: '>=18.0.0'} + '@aws-sdk/client-sagemaker@3.839.0': resolution: {integrity: sha512-OHpvP7LSFgLL15jlAWzM8APjF8EGcKjNpUUGXKfCqz5RiD8yvg9+S4j2kE4eux7QoUhy+xXhsivxa6Nphy+BUw==} engines: {node: '>=18.0.0'} @@ -1724,10 +1747,18 @@ packages: resolution: {integrity: sha512-AZABysUhbfcwXVlMo97/vwHgsfJNF81wypCAowpqAJkSjP2KrqsqHpb71/RoR2w8JGmEnBBXRD4wIxDhnmifWg==} engines: {node: '>=18.0.0'} + '@aws-sdk/client-sso@3.840.0': + resolution: {integrity: sha512-3Zp+FWN2hhmKdpS0Ragi5V2ZPsZNScE3jlbgoJjzjI/roHZqO+e3/+XFN4TlM0DsPKYJNp+1TAjmhxN6rOnfYA==} + engines: {node: '>=18.0.0'} + '@aws-sdk/core@3.839.0': resolution: {integrity: sha512-KdwL5RaK7eUIlOpdOoZ5u+2t4X1rdX/MTZgz3IV/aBzjVUoGsp+uUnbyqXomLQSUitPHp72EE/NHDsvWW/IHvQ==} engines: {node: '>=18.0.0'} + '@aws-sdk/core@3.840.0': + resolution: {integrity: sha512-x3Zgb39tF1h2XpU+yA4OAAQlW6LVEfXNlSedSYJ7HGKXqA/E9h3rWQVpYfhXXVVsLdYXdNw5KBUkoAoruoZSZA==} + engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-cognito-identity@3.839.0': resolution: {integrity: sha512-dXJsdSEVzG+8nIihqVnWzyW8Dc41kNKZEXYguHDb+VM/cIjRSVkaw9jXc+KAvbwcGkEB7BfAuW9VMjxpTR5eAA==} engines: {node: '>=18.0.0'} @@ -1736,54 +1767,126 @@ packages: resolution: {integrity: sha512-cWTadewPPz1OvObZJB+olrgh8VwcgIVcT293ZUT9V0CMF0UU7QaPwJP7uNXcNxltTh+sk1yhjH4UlcnJigZZbA==} engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-env@3.840.0': + resolution: {integrity: sha512-EzF6VcJK7XvQ/G15AVEfJzN2mNXU8fcVpXo4bRyr1S6t2q5zx6UPH/XjDbn18xyUmOq01t+r8gG+TmHEVo18fA==} + engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-http@3.839.0': resolution: {integrity: sha512-fv0BZwrDhWDju4D1MCLT4I2aPjr0dVQ6P+MpqvcGNOA41Oa9UdRhYTV5iuy5NLXzIzoCmnS+XfSq5Kbsf6//xw==} engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-http@3.840.0': + resolution: {integrity: sha512-wbnUiPGLVea6mXbUh04fu+VJmGkQvmToPeTYdHE8eRZq3NRDi3t3WltT+jArLBKD/4NppRpMjf2ju4coMCz91g==} + engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-ini@3.839.0': resolution: {integrity: sha512-GHm0hF4CiDxIDR7TauMaA6iI55uuSqRxMBcqTAHaTPm6+h1A+MS+ysQMxZ+Jvwtoy8WmfTIGrJVxSCw0sK2hvA==} engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-ini@3.840.0': + resolution: {integrity: sha512-7F290BsWydShHb+7InXd+IjJc3mlEIm9I0R57F/Pjl1xZB69MdkhVGCnuETWoBt4g53ktJd6NEjzm/iAhFXFmw==} + engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-node@3.839.0': resolution: {integrity: sha512-7bR+U2h+ft0V8chyeu9Bh/pvau4ZkQMeRt5f0dAULoepZQ77QQVRP4H04yJPTg9DCtqbVULQ3uf5YOp1/08vQw==} engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-node@3.840.0': + resolution: {integrity: sha512-KufP8JnxA31wxklLm63evUPSFApGcH8X86z3mv9SRbpCm5ycgWIGVCTXpTOdgq6rPZrwT9pftzv2/b4mV/9clg==} + engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-process@3.839.0': resolution: {integrity: sha512-qShpekjociUZ+isyQNa0P7jo+0q3N2+0eJDg8SGyP6K6hHTcGfiqxTDps+IKl6NreCPhZCBzyI9mWkP0xSDR6g==} engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-process@3.840.0': + resolution: {integrity: sha512-HkDQWHy8tCI4A0Ps2NVtuVYMv9cB4y/IuD/TdOsqeRIAT12h8jDb98BwQPNLAImAOwOWzZJ8Cu0xtSpX7CQhMw==} + engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-sso@3.839.0': resolution: {integrity: sha512-w10zBLHhU8SBQcdrSPMI02haLoRGZg+gP7mH/Er8VhIXfHefbr7o4NirmB0hwdw/YAH8MLlC9jj7c2SJlsNhYA==} engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-sso@3.840.0': + resolution: {integrity: sha512-2qgdtdd6R0Z1y0KL8gzzwFUGmhBHSUx4zy85L2XV1CXhpRNwV71SVWJqLDVV5RVWVf9mg50Pm3AWrUC0xb0pcA==} + engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-web-identity@3.839.0': resolution: {integrity: sha512-EvqTc7J1kgmiuxknpCp1S60hyMQvmKxsI5uXzQtcogl/N55rxiXEqnCLI5q6p33q91PJegrcMCM5Q17Afhm5qA==} engines: {node: '>=18.0.0'} + '@aws-sdk/credential-provider-web-identity@3.840.0': + resolution: {integrity: sha512-dpEeVXG8uNZSmVXReE4WP0lwoioX2gstk4RnUgrdUE3YaPq8A+hJiVAyc3h+cjDeIqfbsQbZm9qFetKC2LF9dQ==} + engines: {node: '>=18.0.0'} + '@aws-sdk/credential-providers@3.839.0': resolution: {integrity: sha512-hiM7vY2qYAdNT87+Qd3vvfNA+bqhtecsPIduIxkhwispEs9NGcQYtOaG3KQRcHkJBb4kaMYpudVNMXeYUYi2Aw==} engines: {node: '>=18.0.0'} + '@aws-sdk/middleware-bucket-endpoint@3.840.0': + resolution: {integrity: sha512-+gkQNtPwcSMmlwBHFd4saVVS11In6ID1HczNzpM3MXKXRBfSlbZJbCt6wN//AZ8HMklZEik4tcEOG0qa9UY8SQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-expect-continue@3.840.0': + resolution: {integrity: sha512-iJg2r6FKsKKvdiU4oCOuCf7Ro/YE0Q2BT/QyEZN3/Rt8Nr4SAZiQOlcBXOCpGvuIKOEAhvDOUnW3aDHL01PdVw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-flexible-checksums@3.840.0': + resolution: {integrity: sha512-Kg/o2G6o72sdoRH0J+avdcf668gM1bp6O4VeEXpXwUj/urQnV5qiB2q1EYT110INHUKWOLXPND3sQAqh6sTqHw==} + engines: {node: '>=18.0.0'} + '@aws-sdk/middleware-host-header@3.821.0': resolution: {integrity: sha512-xSMR+sopSeWGx5/4pAGhhfMvGBHioVBbqGvDs6pG64xfNwM5vq5s5v6D04e2i+uSTj4qGa71dLUs5I0UzAK3sw==} engines: {node: '>=18.0.0'} + '@aws-sdk/middleware-host-header@3.840.0': + resolution: {integrity: sha512-ub+hXJAbAje94+Ya6c6eL7sYujoE8D4Bumu1NUI8TXjUhVVn0HzVWQjpRLshdLsUp1AW7XyeJaxyajRaJQ8+Xg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-location-constraint@3.840.0': + resolution: {integrity: sha512-KVLD0u0YMF3aQkVF8bdyHAGWSUY6N1Du89htTLgqCcIhSxxAJ9qifrosVZ9jkAzqRW99hcufyt2LylcVU2yoKQ==} + engines: {node: '>=18.0.0'} + '@aws-sdk/middleware-logger@3.821.0': resolution: {integrity: sha512-0cvI0ipf2tGx7fXYEEN5fBeZDz2RnHyb9xftSgUsEq7NBxjV0yTZfLJw6Za5rjE6snC80dRN8+bTNR1tuG89zA==} engines: {node: '>=18.0.0'} + '@aws-sdk/middleware-logger@3.840.0': + resolution: {integrity: sha512-lSV8FvjpdllpGaRspywss4CtXV8M7NNNH+2/j86vMH+YCOZ6fu2T/TyFd/tHwZ92vDfHctWkRbQxg0bagqwovA==} + engines: {node: '>=18.0.0'} + '@aws-sdk/middleware-recursion-detection@3.821.0': resolution: {integrity: sha512-efmaifbhBoqKG3bAoEfDdcM8hn1psF+4qa7ykWuYmfmah59JBeqHLfz5W9m9JoTwoKPkFcVLWZxnyZzAnVBOIg==} engines: {node: '>=18.0.0'} + '@aws-sdk/middleware-recursion-detection@3.840.0': + resolution: {integrity: sha512-Gu7lGDyfddyhIkj1Z1JtrY5NHb5+x/CRiB87GjaSrKxkDaydtX2CU977JIABtt69l9wLbcGDIQ+W0uJ5xPof7g==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-sdk-s3@3.840.0': + resolution: {integrity: sha512-rOUji7CayWN3O09zvvgLzDVQe0HiJdZkxoTS6vzOS3WbbdT7joGdVtAJHtn+x776QT3hHzbKU5gnfhel0o6gQA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-ssec@3.840.0': + resolution: {integrity: sha512-CBZP9t1QbjDFGOrtnUEHL1oAvmnCUUm7p0aPNbIdSzNtH42TNKjPRN3TuEIJDGjkrqpL3MXyDSmNayDcw/XW7Q==} + engines: {node: '>=18.0.0'} + '@aws-sdk/middleware-user-agent@3.839.0': resolution: {integrity: sha512-2u74uRM1JWq6Sf7+3YpjejPM9YkomGt4kWhrmooIBEq1k5r2GTbkH7pNCxBQwBueXM21jAGVDxxeClpTx+5hig==} engines: {node: '>=18.0.0'} + '@aws-sdk/middleware-user-agent@3.840.0': + resolution: {integrity: sha512-hiiMf7BP5ZkAFAvWRcK67Mw/g55ar7OCrvrynC92hunx/xhMkrgSLM0EXIZ1oTn3uql9kH/qqGF0nqsK6K555A==} + engines: {node: '>=18.0.0'} + '@aws-sdk/nested-clients@3.839.0': resolution: {integrity: sha512-Glic0pg2THYP3aRhJORwJJBe1JLtJoEdWV/MFZNyzCklfMwEzpWtZAyxy+tQyFmMeW50uBAnh2R0jhMMcf257w==} engines: {node: '>=18.0.0'} + '@aws-sdk/nested-clients@3.840.0': + resolution: {integrity: sha512-LXYYo9+n4hRqnRSIMXLBb+BLz+cEmjMtTudwK1BF6Bn2RfdDv29KuyeDRrPCS3TwKl7ZKmXUmE9n5UuHAPfBpA==} + engines: {node: '>=18.0.0'} + '@aws-sdk/protocol-http@3.374.0': resolution: {integrity: sha512-9WpRUbINdGroV3HiZZIBoJvL2ndoWk39OfwxWs2otxByppJZNN14bg/lvCx5e8ggHUti7IBk5rb0nqQZ4m05pg==} engines: {node: '>=14.0.0'} @@ -1793,6 +1896,18 @@ packages: resolution: {integrity: sha512-t8og+lRCIIy5nlId0bScNpCkif8sc0LhmtaKsbm0ZPm3sCa/WhCbSZibjbZ28FNjVCV+p0D9RYZx0VDDbtWyjw==} engines: {node: '>=18.0.0'} + '@aws-sdk/region-config-resolver@3.840.0': + resolution: {integrity: sha512-Qjnxd/yDv9KpIMWr90ZDPtRj0v75AqGC92Lm9+oHXZ8p1MjG5JE2CW0HL8JRgK9iKzgKBL7pPQRXI8FkvEVfrA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/s3-request-presigner@3.840.0': + resolution: {integrity: sha512-1jcrhVoSZjiAQJGNswI0RGR36/+OG6yTV42wQamHdNHk+/68dn9MGTUVr+58AEFOyEAPE/EvkiYRD6n5WkUjMg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/signature-v4-multi-region@3.840.0': + resolution: {integrity: sha512-8AoVgHrkSfhvGPtwx23hIUO4MmMnux2pjnso1lrLZGqxfElM6jm2w4jTNLlNXk8uKHGyX89HaAIuT0lL6dJj9g==} + engines: {node: '>=18.0.0'} + '@aws-sdk/signature-v4@3.374.0': resolution: {integrity: sha512-2xLJvSdzcZZAg0lsDLUAuSQuihzK0dcxIK7WmfuJeF7DGKJFmp9czQmz5f3qiDz6IDQzvgK1M9vtJSVCslJbyQ==} engines: {node: '>=14.0.0'} @@ -1802,14 +1917,34 @@ packages: resolution: {integrity: sha512-2nlafqdSbet/2WtYIoZ7KEGFowFonPBDYlTjrUvwU2yooE10VhvzhLSCTB2aKIVzo2Z2wL5WGFQsqAY5QwK6Bw==} engines: {node: '>=18.0.0'} + '@aws-sdk/token-providers@3.840.0': + resolution: {integrity: sha512-6BuTOLTXvmgwjK7ve7aTg9JaWFdM5UoMolLVPMyh3wTv9Ufalh8oklxYHUBIxsKkBGO2WiHXytveuxH6tAgTYg==} + engines: {node: '>=18.0.0'} + '@aws-sdk/types@3.821.0': resolution: {integrity: sha512-Znroqdai1a90TlxGaJ+FK1lwC0fHpo97Xjsp5UKGR5JODYm7f9+/fF17ebO1KdoBr/Rm0UIFiF5VmI8ts9F1eA==} engines: {node: '>=18.0.0'} + '@aws-sdk/types@3.840.0': + resolution: {integrity: sha512-xliuHaUFZxEx1NSXeLLZ9Dyu6+EJVQKEoD+yM+zqUo3YDZ7medKJWY6fIOKiPX/N7XbLdBYwajb15Q7IL8KkeA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-arn-parser@3.804.0': + resolution: {integrity: sha512-wmBJqn1DRXnZu3b4EkE6CWnoWMo1ZMvlfkqU5zPz67xx1GMaXlDCchFvKAXMjk4jn/L1O3tKnoFDNsoLV1kgNQ==} + engines: {node: '>=18.0.0'} + '@aws-sdk/util-endpoints@3.828.0': resolution: {integrity: sha512-RvKch111SblqdkPzg3oCIdlGxlQs+k+P7Etory9FmxPHyPDvsP1j1c74PmgYqtzzMWmoXTjd+c9naUHh9xG8xg==} engines: {node: '>=18.0.0'} + '@aws-sdk/util-endpoints@3.840.0': + resolution: {integrity: sha512-eqE9ROdg/Kk0rj3poutyRCFauPDXIf/WSvCqFiRDDVi6QOnCv/M0g2XW8/jSvkJlOyaXkNCptapIp6BeeFFGYw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-format-url@3.840.0': + resolution: {integrity: sha512-VB1PWyI1TQPiPvg4w7tgUGGQER1xxXPNUqfh3baxUSFi1Oh8wHrDnFywkxLm3NMmgDmnLnSZ5Q326qAoyqKLSg==} + engines: {node: '>=18.0.0'} + '@aws-sdk/util-locate-window@3.804.0': resolution: {integrity: sha512-zVoRfpmBVPodYlnMjgVjfGoEZagyRF5IPn3Uo6ZvOZp24chnW/FRstH7ESDHDDRga4z3V+ElUQHKpFDXWyBW5A==} engines: {node: '>=18.0.0'} @@ -1817,6 +1952,9 @@ packages: '@aws-sdk/util-user-agent-browser@3.821.0': resolution: {integrity: sha512-irWZHyM0Jr1xhC+38OuZ7JB6OXMLPZlj48thElpsO1ZSLRkLZx5+I7VV6k3sp2yZ7BYbKz/G2ojSv4wdm7XTLw==} + '@aws-sdk/util-user-agent-browser@3.840.0': + resolution: {integrity: sha512-JdyZM3EhhL4PqwFpttZu1afDpPJCCc3eyZOLi+srpX11LsGj6sThf47TYQN75HT1CarZ7cCdQHGzP2uy3/xHfQ==} + '@aws-sdk/util-user-agent-node@3.839.0': resolution: {integrity: sha512-MuunkIG1bJVMtTH7MbjXOrhHleU5wjHz5eCAUc6vj7M9rwol71nqjj9b8RLnkO5gsJcKc29Qk8iV6xQuzKWNMw==} engines: {node: '>=18.0.0'} @@ -1826,6 +1964,15 @@ packages: aws-crt: optional: true + '@aws-sdk/util-user-agent-node@3.840.0': + resolution: {integrity: sha512-Fy5JUEDQU1tPm2Yw/YqRYYc27W5+QD/J4mYvQvdWjUGZLB5q3eLFMGD35Uc28ZFoGMufPr4OCxK/bRfWROBRHQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + aws-crt: '>=1.0.0' + peerDependenciesMeta: + aws-crt: + optional: true + '@aws-sdk/util-utf8-browser@3.259.0': resolution: {integrity: sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==} @@ -5312,6 +5459,14 @@ packages: resolution: {integrity: sha512-gJnEjZMvigPDQWHrW3oPrFhQtkrgqBkyjj3pCIdF3A5M6vsZODG93KNlfJprv6bp4245bdT32fsHK4kkH3KYDA==} engines: {node: '>=18.0.0'} + '@smithy/chunked-blob-reader-native@4.0.0': + resolution: {integrity: sha512-R9wM2yPmfEMsUmlMlIgSzOyICs0x9uu7UTHoccMyt7BWw8shcGM8HqB355+BZCPBcySvbTYMs62EgEQkNxz2ig==} + engines: {node: '>=18.0.0'} + + '@smithy/chunked-blob-reader@5.0.0': + resolution: {integrity: sha512-+sKqDBQqb036hh4NPaUiEkYFkTUGYzRsn3EuFhyfQfMy6oGHEUJDurLP9Ufb5dasr/XiAmPNMr6wa9afjQB+Gw==} + engines: {node: '>=18.0.0'} + '@smithy/config-resolver@4.1.4': resolution: {integrity: sha512-prmU+rDddxHOH0oNcwemL+SwnzcG65sBF2yXRO7aeXIn/xTlq2pX7JLVbkBnVLowHLg4/OL4+jBmv9hVrVGS+w==} engines: {node: '>=18.0.0'} @@ -5327,14 +5482,42 @@ packages: '@smithy/eventstream-codec@1.1.0': resolution: {integrity: sha512-3tEbUb8t8an226jKB6V/Q2XU/J53lCwCzULuBPEaF4JjSh+FlCMp7TmogE/Aij5J9DwlsZ4VAD/IRDuQ/0ZtMw==} + '@smithy/eventstream-codec@4.0.4': + resolution: {integrity: sha512-7XoWfZqWb/QoR/rAU4VSi0mWnO2vu9/ltS6JZ5ZSZv0eovLVfDfu0/AX4ub33RsJTOth3TiFWSHS5YdztvFnig==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-browser@4.0.4': + resolution: {integrity: sha512-3fb/9SYaYqbpy/z/H3yIi0bYKyAa89y6xPmIqwr2vQiUT2St+avRt8UKwsWt9fEdEasc5d/V+QjrviRaX1JRFA==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-config-resolver@4.1.2': + resolution: {integrity: sha512-JGtambizrWP50xHgbzZI04IWU7LdI0nh/wGbqH3sJesYToMi2j/DcoElqyOcqEIG/D4tNyxgRuaqBXWE3zOFhQ==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-node@4.0.4': + resolution: {integrity: sha512-RD6UwNZ5zISpOWPuhVgRz60GkSIp0dy1fuZmj4RYmqLVRtejFqQ16WmfYDdoSoAjlp1LX+FnZo+/hkdmyyGZ1w==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-universal@4.0.4': + resolution: {integrity: sha512-UeJpOmLGhq1SLox79QWw/0n2PFX+oPRE1ZyRMxPIaFEfCqWaqpB7BU9C8kpPOGEhLF7AwEqfFbtwNxGy4ReENA==} + engines: {node: '>=18.0.0'} + '@smithy/fetch-http-handler@5.0.4': resolution: {integrity: sha512-AMtBR5pHppYMVD7z7G+OlHHAcgAN7v0kVKEpHuTO4Gb199Gowh0taYi9oDStFeUhetkeP55JLSVlTW1n9rFtUw==} engines: {node: '>=18.0.0'} + '@smithy/hash-blob-browser@4.0.4': + resolution: {integrity: sha512-WszRiACJiQV3QG6XMV44i5YWlkrlsM5Yxgz4jvsksuu7LDXA6wAtypfPajtNTadzpJy3KyJPoWehYpmZGKUFIQ==} + engines: {node: '>=18.0.0'} + '@smithy/hash-node@4.0.4': resolution: {integrity: sha512-qnbTPUhCVnCgBp4z4BUJUhOEkVwxiEi1cyFM+Zj6o+aY8OFGxUQleKWq8ltgp3dujuhXojIvJWdoqpm6dVO3lQ==} engines: {node: '>=18.0.0'} + '@smithy/hash-stream-node@4.0.4': + resolution: {integrity: sha512-wHo0d8GXyVmpmMh/qOR0R7Y46/G1y6OR8U+bSTB4ppEzRxd1xVAQ9xOE9hOc0bSjhz0ujCPAbfNLkLrpa6cevg==} + engines: {node: '>=18.0.0'} + '@smithy/invalid-dependency@4.0.4': resolution: {integrity: sha512-bNYMi7WKTJHu0gn26wg8OscncTt1t2b8KcsZxvOv56XA6cyXtOAAAaNP7+m45xfppXfOatXF3Sb1MNsLUgVLTw==} engines: {node: '>=18.0.0'} @@ -5351,6 +5534,10 @@ packages: resolution: {integrity: sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==} engines: {node: '>=18.0.0'} + '@smithy/md5-js@4.0.4': + resolution: {integrity: sha512-uGLBVqcOwrLvGh/v/jw423yWHq/ofUGK1W31M2TNspLQbUV1Va0F5kTxtirkoHawODAZcjXTSGi7JwbnPcDPJg==} + engines: {node: '>=18.0.0'} + '@smithy/middleware-content-length@4.0.4': resolution: {integrity: sha512-F7gDyfI2BB1Kc+4M6rpuOLne5LOcEknH1n6UQB69qv+HucXBR1rkzXBnQTB2q46sFy1PM/zuSJOB532yc8bg3w==} engines: {node: '>=18.0.0'} @@ -11895,15 +12082,36 @@ snapshots: '@aws-crypto/crc32@3.0.0': dependencies: '@aws-crypto/util': 3.0.0 - '@aws-sdk/types': 3.821.0 + '@aws-sdk/types': 3.840.0 tslib: 1.14.1 + '@aws-crypto/crc32@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.840.0 + tslib: 2.8.1 + + '@aws-crypto/crc32c@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.840.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.840.0 + '@aws-sdk/util-locate-window': 3.804.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.821.0 + '@aws-sdk/types': 3.840.0 '@aws-sdk/util-locate-window': 3.804.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 @@ -11911,7 +12119,7 @@ snapshots: '@aws-crypto/sha256-js@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.821.0 + '@aws-sdk/types': 3.840.0 tslib: 2.8.1 '@aws-crypto/supports-web-crypto@5.2.0': @@ -11920,13 +12128,13 @@ snapshots: '@aws-crypto/util@3.0.0': dependencies: - '@aws-sdk/types': 3.821.0 + '@aws-sdk/types': 3.840.0 '@aws-sdk/util-utf8-browser': 3.259.0 tslib: 1.14.1 '@aws-crypto/util@5.2.0': dependencies: - '@aws-sdk/types': 3.821.0 + '@aws-sdk/types': 3.840.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 @@ -11974,6 +12182,69 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/client-s3@3.840.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.840.0 + '@aws-sdk/credential-provider-node': 3.840.0 + '@aws-sdk/middleware-bucket-endpoint': 3.840.0 + '@aws-sdk/middleware-expect-continue': 3.840.0 + '@aws-sdk/middleware-flexible-checksums': 3.840.0 + '@aws-sdk/middleware-host-header': 3.840.0 + '@aws-sdk/middleware-location-constraint': 3.840.0 + '@aws-sdk/middleware-logger': 3.840.0 + '@aws-sdk/middleware-recursion-detection': 3.840.0 + '@aws-sdk/middleware-sdk-s3': 3.840.0 + '@aws-sdk/middleware-ssec': 3.840.0 + '@aws-sdk/middleware-user-agent': 3.840.0 + '@aws-sdk/region-config-resolver': 3.840.0 + '@aws-sdk/signature-v4-multi-region': 3.840.0 + '@aws-sdk/types': 3.840.0 + '@aws-sdk/util-endpoints': 3.840.0 + '@aws-sdk/util-user-agent-browser': 3.840.0 + '@aws-sdk/util-user-agent-node': 3.840.0 + '@aws-sdk/xml-builder': 3.821.0 + '@smithy/config-resolver': 4.1.4 + '@smithy/core': 3.6.0 + '@smithy/eventstream-serde-browser': 4.0.4 + '@smithy/eventstream-serde-config-resolver': 4.1.2 + '@smithy/eventstream-serde-node': 4.0.4 + '@smithy/fetch-http-handler': 5.0.4 + '@smithy/hash-blob-browser': 4.0.4 + '@smithy/hash-node': 4.0.4 + '@smithy/hash-stream-node': 4.0.4 + '@smithy/invalid-dependency': 4.0.4 + '@smithy/md5-js': 4.0.4 + '@smithy/middleware-content-length': 4.0.4 + '@smithy/middleware-endpoint': 4.1.13 + '@smithy/middleware-retry': 4.1.14 + '@smithy/middleware-serde': 4.0.8 + '@smithy/middleware-stack': 4.0.4 + '@smithy/node-config-provider': 4.1.3 + '@smithy/node-http-handler': 4.0.6 + '@smithy/protocol-http': 5.1.2 + '@smithy/smithy-client': 4.4.5 + '@smithy/types': 4.3.1 + '@smithy/url-parser': 4.0.4 + '@smithy/util-base64': 4.0.0 + '@smithy/util-body-length-browser': 4.0.0 + '@smithy/util-body-length-node': 4.0.0 + '@smithy/util-defaults-mode-browser': 4.0.21 + '@smithy/util-defaults-mode-node': 4.0.21 + '@smithy/util-endpoints': 3.0.6 + '@smithy/util-middleware': 4.0.4 + '@smithy/util-retry': 4.0.6 + '@smithy/util-stream': 4.2.2 + '@smithy/util-utf8': 4.0.0 + '@smithy/util-waiter': 4.0.6 + '@types/uuid': 9.0.8 + tslib: 2.8.1 + uuid: 9.0.1 + transitivePeerDependencies: + - aws-crt + '@aws-sdk/client-sagemaker@3.839.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 @@ -12064,6 +12335,49 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/client-sso@3.840.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.840.0 + '@aws-sdk/middleware-host-header': 3.840.0 + '@aws-sdk/middleware-logger': 3.840.0 + '@aws-sdk/middleware-recursion-detection': 3.840.0 + '@aws-sdk/middleware-user-agent': 3.840.0 + '@aws-sdk/region-config-resolver': 3.840.0 + '@aws-sdk/types': 3.840.0 + '@aws-sdk/util-endpoints': 3.840.0 + '@aws-sdk/util-user-agent-browser': 3.840.0 + '@aws-sdk/util-user-agent-node': 3.840.0 + '@smithy/config-resolver': 4.1.4 + '@smithy/core': 3.6.0 + '@smithy/fetch-http-handler': 5.0.4 + '@smithy/hash-node': 4.0.4 + '@smithy/invalid-dependency': 4.0.4 + '@smithy/middleware-content-length': 4.0.4 + '@smithy/middleware-endpoint': 4.1.13 + '@smithy/middleware-retry': 4.1.14 + '@smithy/middleware-serde': 4.0.8 + '@smithy/middleware-stack': 4.0.4 + '@smithy/node-config-provider': 4.1.3 + '@smithy/node-http-handler': 4.0.6 + '@smithy/protocol-http': 5.1.2 + '@smithy/smithy-client': 4.4.5 + '@smithy/types': 4.3.1 + '@smithy/url-parser': 4.0.4 + '@smithy/util-base64': 4.0.0 + '@smithy/util-body-length-browser': 4.0.0 + '@smithy/util-body-length-node': 4.0.0 + '@smithy/util-defaults-mode-browser': 4.0.21 + '@smithy/util-defaults-mode-node': 4.0.21 + '@smithy/util-endpoints': 3.0.6 + '@smithy/util-middleware': 4.0.4 + '@smithy/util-retry': 4.0.6 + '@smithy/util-utf8': 4.0.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + '@aws-sdk/core@3.839.0': dependencies: '@aws-sdk/types': 3.821.0 @@ -12082,6 +12396,24 @@ snapshots: fast-xml-parser: 4.4.1 tslib: 2.8.1 + '@aws-sdk/core@3.840.0': + dependencies: + '@aws-sdk/types': 3.840.0 + '@aws-sdk/xml-builder': 3.821.0 + '@smithy/core': 3.6.0 + '@smithy/node-config-provider': 4.1.3 + '@smithy/property-provider': 4.0.4 + '@smithy/protocol-http': 5.1.2 + '@smithy/signature-v4': 5.1.2 + '@smithy/smithy-client': 4.4.5 + '@smithy/types': 4.3.1 + '@smithy/util-base64': 4.0.0 + '@smithy/util-body-length-browser': 4.0.0 + '@smithy/util-middleware': 4.0.4 + '@smithy/util-utf8': 4.0.0 + fast-xml-parser: 4.4.1 + tslib: 2.8.1 + '@aws-sdk/credential-provider-cognito-identity@3.839.0': dependencies: '@aws-sdk/client-cognito-identity': 3.839.0 @@ -12100,6 +12432,14 @@ snapshots: '@smithy/types': 4.3.1 tslib: 2.8.1 + '@aws-sdk/credential-provider-env@3.840.0': + dependencies: + '@aws-sdk/core': 3.840.0 + '@aws-sdk/types': 3.840.0 + '@smithy/property-provider': 4.0.4 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + '@aws-sdk/credential-provider-http@3.839.0': dependencies: '@aws-sdk/core': 3.839.0 @@ -12113,6 +12453,19 @@ snapshots: '@smithy/util-stream': 4.2.2 tslib: 2.8.1 + '@aws-sdk/credential-provider-http@3.840.0': + dependencies: + '@aws-sdk/core': 3.840.0 + '@aws-sdk/types': 3.840.0 + '@smithy/fetch-http-handler': 5.0.4 + '@smithy/node-http-handler': 4.0.6 + '@smithy/property-provider': 4.0.4 + '@smithy/protocol-http': 5.1.2 + '@smithy/smithy-client': 4.4.5 + '@smithy/types': 4.3.1 + '@smithy/util-stream': 4.2.2 + tslib: 2.8.1 + '@aws-sdk/credential-provider-ini@3.839.0': dependencies: '@aws-sdk/core': 3.839.0 @@ -12131,6 +12484,24 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/credential-provider-ini@3.840.0': + dependencies: + '@aws-sdk/core': 3.840.0 + '@aws-sdk/credential-provider-env': 3.840.0 + '@aws-sdk/credential-provider-http': 3.840.0 + '@aws-sdk/credential-provider-process': 3.840.0 + '@aws-sdk/credential-provider-sso': 3.840.0 + '@aws-sdk/credential-provider-web-identity': 3.840.0 + '@aws-sdk/nested-clients': 3.840.0 + '@aws-sdk/types': 3.840.0 + '@smithy/credential-provider-imds': 4.0.6 + '@smithy/property-provider': 4.0.4 + '@smithy/shared-ini-file-loader': 4.0.4 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + '@aws-sdk/credential-provider-node@3.839.0': dependencies: '@aws-sdk/credential-provider-env': 3.839.0 @@ -12148,6 +12519,23 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/credential-provider-node@3.840.0': + dependencies: + '@aws-sdk/credential-provider-env': 3.840.0 + '@aws-sdk/credential-provider-http': 3.840.0 + '@aws-sdk/credential-provider-ini': 3.840.0 + '@aws-sdk/credential-provider-process': 3.840.0 + '@aws-sdk/credential-provider-sso': 3.840.0 + '@aws-sdk/credential-provider-web-identity': 3.840.0 + '@aws-sdk/types': 3.840.0 + '@smithy/credential-provider-imds': 4.0.6 + '@smithy/property-provider': 4.0.4 + '@smithy/shared-ini-file-loader': 4.0.4 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + '@aws-sdk/credential-provider-process@3.839.0': dependencies: '@aws-sdk/core': 3.839.0 @@ -12157,6 +12545,15 @@ snapshots: '@smithy/types': 4.3.1 tslib: 2.8.1 + '@aws-sdk/credential-provider-process@3.840.0': + dependencies: + '@aws-sdk/core': 3.840.0 + '@aws-sdk/types': 3.840.0 + '@smithy/property-provider': 4.0.4 + '@smithy/shared-ini-file-loader': 4.0.4 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + '@aws-sdk/credential-provider-sso@3.839.0': dependencies: '@aws-sdk/client-sso': 3.839.0 @@ -12170,6 +12567,19 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/credential-provider-sso@3.840.0': + dependencies: + '@aws-sdk/client-sso': 3.840.0 + '@aws-sdk/core': 3.840.0 + '@aws-sdk/token-providers': 3.840.0 + '@aws-sdk/types': 3.840.0 + '@smithy/property-provider': 4.0.4 + '@smithy/shared-ini-file-loader': 4.0.4 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + '@aws-sdk/credential-provider-web-identity@3.839.0': dependencies: '@aws-sdk/core': 3.839.0 @@ -12181,6 +12591,17 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/credential-provider-web-identity@3.840.0': + dependencies: + '@aws-sdk/core': 3.840.0 + '@aws-sdk/nested-clients': 3.840.0 + '@aws-sdk/types': 3.840.0 + '@smithy/property-provider': 4.0.4 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + '@aws-sdk/credential-providers@3.839.0': dependencies: '@aws-sdk/client-cognito-identity': 3.839.0 @@ -12205,6 +12626,39 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/middleware-bucket-endpoint@3.840.0': + dependencies: + '@aws-sdk/types': 3.840.0 + '@aws-sdk/util-arn-parser': 3.804.0 + '@smithy/node-config-provider': 4.1.3 + '@smithy/protocol-http': 5.1.2 + '@smithy/types': 4.3.1 + '@smithy/util-config-provider': 4.0.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-expect-continue@3.840.0': + dependencies: + '@aws-sdk/types': 3.840.0 + '@smithy/protocol-http': 5.1.2 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + + '@aws-sdk/middleware-flexible-checksums@3.840.0': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@aws-crypto/crc32c': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/core': 3.840.0 + '@aws-sdk/types': 3.840.0 + '@smithy/is-array-buffer': 4.0.0 + '@smithy/node-config-provider': 4.1.3 + '@smithy/protocol-http': 5.1.2 + '@smithy/types': 4.3.1 + '@smithy/util-middleware': 4.0.4 + '@smithy/util-stream': 4.2.2 + '@smithy/util-utf8': 4.0.0 + tslib: 2.8.1 + '@aws-sdk/middleware-host-header@3.821.0': dependencies: '@aws-sdk/types': 3.821.0 @@ -12212,12 +12666,31 @@ snapshots: '@smithy/types': 4.3.1 tslib: 2.8.1 + '@aws-sdk/middleware-host-header@3.840.0': + dependencies: + '@aws-sdk/types': 3.840.0 + '@smithy/protocol-http': 5.1.2 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + + '@aws-sdk/middleware-location-constraint@3.840.0': + dependencies: + '@aws-sdk/types': 3.840.0 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + '@aws-sdk/middleware-logger@3.821.0': dependencies: '@aws-sdk/types': 3.821.0 '@smithy/types': 4.3.1 tslib: 2.8.1 + '@aws-sdk/middleware-logger@3.840.0': + dependencies: + '@aws-sdk/types': 3.840.0 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + '@aws-sdk/middleware-recursion-detection@3.821.0': dependencies: '@aws-sdk/types': 3.821.0 @@ -12225,6 +12698,36 @@ snapshots: '@smithy/types': 4.3.1 tslib: 2.8.1 + '@aws-sdk/middleware-recursion-detection@3.840.0': + dependencies: + '@aws-sdk/types': 3.840.0 + '@smithy/protocol-http': 5.1.2 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + + '@aws-sdk/middleware-sdk-s3@3.840.0': + dependencies: + '@aws-sdk/core': 3.840.0 + '@aws-sdk/types': 3.840.0 + '@aws-sdk/util-arn-parser': 3.804.0 + '@smithy/core': 3.6.0 + '@smithy/node-config-provider': 4.1.3 + '@smithy/protocol-http': 5.1.2 + '@smithy/signature-v4': 5.1.2 + '@smithy/smithy-client': 4.4.5 + '@smithy/types': 4.3.1 + '@smithy/util-config-provider': 4.0.0 + '@smithy/util-middleware': 4.0.4 + '@smithy/util-stream': 4.2.2 + '@smithy/util-utf8': 4.0.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-ssec@3.840.0': + dependencies: + '@aws-sdk/types': 3.840.0 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + '@aws-sdk/middleware-user-agent@3.839.0': dependencies: '@aws-sdk/core': 3.839.0 @@ -12235,6 +12738,16 @@ snapshots: '@smithy/types': 4.3.1 tslib: 2.8.1 + '@aws-sdk/middleware-user-agent@3.840.0': + dependencies: + '@aws-sdk/core': 3.840.0 + '@aws-sdk/types': 3.840.0 + '@aws-sdk/util-endpoints': 3.840.0 + '@smithy/core': 3.6.0 + '@smithy/protocol-http': 5.1.2 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + '@aws-sdk/nested-clients@3.839.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 @@ -12278,6 +12791,49 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/nested-clients@3.840.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.840.0 + '@aws-sdk/middleware-host-header': 3.840.0 + '@aws-sdk/middleware-logger': 3.840.0 + '@aws-sdk/middleware-recursion-detection': 3.840.0 + '@aws-sdk/middleware-user-agent': 3.840.0 + '@aws-sdk/region-config-resolver': 3.840.0 + '@aws-sdk/types': 3.840.0 + '@aws-sdk/util-endpoints': 3.840.0 + '@aws-sdk/util-user-agent-browser': 3.840.0 + '@aws-sdk/util-user-agent-node': 3.840.0 + '@smithy/config-resolver': 4.1.4 + '@smithy/core': 3.6.0 + '@smithy/fetch-http-handler': 5.0.4 + '@smithy/hash-node': 4.0.4 + '@smithy/invalid-dependency': 4.0.4 + '@smithy/middleware-content-length': 4.0.4 + '@smithy/middleware-endpoint': 4.1.13 + '@smithy/middleware-retry': 4.1.14 + '@smithy/middleware-serde': 4.0.8 + '@smithy/middleware-stack': 4.0.4 + '@smithy/node-config-provider': 4.1.3 + '@smithy/node-http-handler': 4.0.6 + '@smithy/protocol-http': 5.1.2 + '@smithy/smithy-client': 4.4.5 + '@smithy/types': 4.3.1 + '@smithy/url-parser': 4.0.4 + '@smithy/util-base64': 4.0.0 + '@smithy/util-body-length-browser': 4.0.0 + '@smithy/util-body-length-node': 4.0.0 + '@smithy/util-defaults-mode-browser': 4.0.21 + '@smithy/util-defaults-mode-node': 4.0.21 + '@smithy/util-endpoints': 3.0.6 + '@smithy/util-middleware': 4.0.4 + '@smithy/util-retry': 4.0.6 + '@smithy/util-utf8': 4.0.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + '@aws-sdk/protocol-http@3.374.0': dependencies: '@smithy/protocol-http': 1.2.0 @@ -12292,6 +12848,35 @@ snapshots: '@smithy/util-middleware': 4.0.4 tslib: 2.8.1 + '@aws-sdk/region-config-resolver@3.840.0': + dependencies: + '@aws-sdk/types': 3.840.0 + '@smithy/node-config-provider': 4.1.3 + '@smithy/types': 4.3.1 + '@smithy/util-config-provider': 4.0.0 + '@smithy/util-middleware': 4.0.4 + tslib: 2.8.1 + + '@aws-sdk/s3-request-presigner@3.840.0': + dependencies: + '@aws-sdk/signature-v4-multi-region': 3.840.0 + '@aws-sdk/types': 3.840.0 + '@aws-sdk/util-format-url': 3.840.0 + '@smithy/middleware-endpoint': 4.1.13 + '@smithy/protocol-http': 5.1.2 + '@smithy/smithy-client': 4.4.5 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + + '@aws-sdk/signature-v4-multi-region@3.840.0': + dependencies: + '@aws-sdk/middleware-sdk-s3': 3.840.0 + '@aws-sdk/types': 3.840.0 + '@smithy/protocol-http': 5.1.2 + '@smithy/signature-v4': 5.1.2 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + '@aws-sdk/signature-v4@3.374.0': dependencies: '@smithy/signature-v4': 1.1.0 @@ -12309,11 +12894,32 @@ snapshots: transitivePeerDependencies: - aws-crt + '@aws-sdk/token-providers@3.840.0': + dependencies: + '@aws-sdk/core': 3.840.0 + '@aws-sdk/nested-clients': 3.840.0 + '@aws-sdk/types': 3.840.0 + '@smithy/property-provider': 4.0.4 + '@smithy/shared-ini-file-loader': 4.0.4 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + '@aws-sdk/types@3.821.0': dependencies: '@smithy/types': 4.3.1 tslib: 2.8.1 + '@aws-sdk/types@3.840.0': + dependencies: + '@smithy/types': 4.3.1 + tslib: 2.8.1 + + '@aws-sdk/util-arn-parser@3.804.0': + dependencies: + tslib: 2.8.1 + '@aws-sdk/util-endpoints@3.828.0': dependencies: '@aws-sdk/types': 3.821.0 @@ -12321,6 +12927,20 @@ snapshots: '@smithy/util-endpoints': 3.0.6 tslib: 2.8.1 + '@aws-sdk/util-endpoints@3.840.0': + dependencies: + '@aws-sdk/types': 3.840.0 + '@smithy/types': 4.3.1 + '@smithy/util-endpoints': 3.0.6 + tslib: 2.8.1 + + '@aws-sdk/util-format-url@3.840.0': + dependencies: + '@aws-sdk/types': 3.840.0 + '@smithy/querystring-builder': 4.0.4 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + '@aws-sdk/util-locate-window@3.804.0': dependencies: tslib: 2.8.1 @@ -12332,6 +12952,13 @@ snapshots: bowser: 2.11.0 tslib: 2.8.1 + '@aws-sdk/util-user-agent-browser@3.840.0': + dependencies: + '@aws-sdk/types': 3.840.0 + '@smithy/types': 4.3.1 + bowser: 2.11.0 + tslib: 2.8.1 + '@aws-sdk/util-user-agent-node@3.839.0': dependencies: '@aws-sdk/middleware-user-agent': 3.839.0 @@ -12340,6 +12967,14 @@ snapshots: '@smithy/types': 4.3.1 tslib: 2.8.1 + '@aws-sdk/util-user-agent-node@3.840.0': + dependencies: + '@aws-sdk/middleware-user-agent': 3.840.0 + '@aws-sdk/types': 3.840.0 + '@smithy/node-config-provider': 4.1.3 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + '@aws-sdk/util-utf8-browser@3.259.0': dependencies: tslib: 2.8.1 @@ -16084,6 +16719,15 @@ snapshots: '@smithy/types': 4.3.1 tslib: 2.8.1 + '@smithy/chunked-blob-reader-native@4.0.0': + dependencies: + '@smithy/util-base64': 4.0.0 + tslib: 2.8.1 + + '@smithy/chunked-blob-reader@5.0.0': + dependencies: + tslib: 2.8.1 + '@smithy/config-resolver@4.1.4': dependencies: '@smithy/node-config-provider': 4.1.3 @@ -16119,6 +16763,36 @@ snapshots: '@smithy/util-hex-encoding': 1.1.0 tslib: 2.8.1 + '@smithy/eventstream-codec@4.0.4': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@smithy/types': 4.3.1 + '@smithy/util-hex-encoding': 4.0.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-browser@4.0.4': + dependencies: + '@smithy/eventstream-serde-universal': 4.0.4 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + + '@smithy/eventstream-serde-config-resolver@4.1.2': + dependencies: + '@smithy/types': 4.3.1 + tslib: 2.8.1 + + '@smithy/eventstream-serde-node@4.0.4': + dependencies: + '@smithy/eventstream-serde-universal': 4.0.4 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + + '@smithy/eventstream-serde-universal@4.0.4': + dependencies: + '@smithy/eventstream-codec': 4.0.4 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + '@smithy/fetch-http-handler@5.0.4': dependencies: '@smithy/protocol-http': 5.1.2 @@ -16127,6 +16801,13 @@ snapshots: '@smithy/util-base64': 4.0.0 tslib: 2.8.1 + '@smithy/hash-blob-browser@4.0.4': + dependencies: + '@smithy/chunked-blob-reader': 5.0.0 + '@smithy/chunked-blob-reader-native': 4.0.0 + '@smithy/types': 4.3.1 + tslib: 2.8.1 + '@smithy/hash-node@4.0.4': dependencies: '@smithy/types': 4.3.1 @@ -16134,6 +16815,12 @@ snapshots: '@smithy/util-utf8': 4.0.0 tslib: 2.8.1 + '@smithy/hash-stream-node@4.0.4': + dependencies: + '@smithy/types': 4.3.1 + '@smithy/util-utf8': 4.0.0 + tslib: 2.8.1 + '@smithy/invalid-dependency@4.0.4': dependencies: '@smithy/types': 4.3.1 @@ -16151,6 +16838,12 @@ snapshots: dependencies: tslib: 2.8.1 + '@smithy/md5-js@4.0.4': + dependencies: + '@smithy/types': 4.3.1 + '@smithy/util-utf8': 4.0.0 + tslib: 2.8.1 + '@smithy/middleware-content-length@4.0.4': dependencies: '@smithy/protocol-http': 5.1.2