import { P as Part, S as S3CallOptions, M as MultipartUpload, a as S3ApiOperations, b as S3BaseStorage } from "../../packem_shared/s3-base-storage.d-nOe1N0BL.js"; import { F as File, s as MetaStorageOptions, f as BaseStorageOptions, C as ConditionalSupport, M as MetaStorage, y as UploadPostOptions, z as UploadPostPolicy, i as FileQuery, O as OperationOptions, e as FileInit } from "../../packem_shared/storage.d-Cnjmzau5.js"; import { Readable } from 'node:stream'; import { AwsClient } from 'aws4fetch'; import { b as HttpError } from "../../packem_shared/types.d-DFh9698o.js"; import 'lru-cache'; import 'node:crypto'; import 'node:http'; declare class AwsLightFile extends File { Parts?: Part[]; UploadId?: string; uri?: string; partsUrls?: string[]; partSize?: number; } interface AwsLightClientConfig { accessKeyId: string; endpoint?: string; region: string; secretAccessKey: string; service?: string; sessionToken?: string; } type AwsLightMetaStorageOptions = AwsLightClientConfig & MetaStorageOptions & { bucket?: string; }; type AwsLightStorageOptions = AwsLightClientConfig & BaseStorageOptions & { /** * S3 bucket name. */ bucket?: string; /** * Force compatible client upload directly to S3 storage */ clientDirectUpload?: boolean; /** * Send conditional (ETag) requests and advertise them in `Files.capabilities.conditional`. * Defaults to `true` for AWS S3 and `false` when a custom `endpoint` is set, because S3-compatible * services differ in which `If-Match` / `If-None-Match` headers they honour. Set it explicitly to * override the detection: `true` enables every kind, an object only the kinds set to `true` * (`create` / `replace` send the predicate on CompleteMultipartUpload, `read` on GetObject, * `delete` on DeleteObject, `copy` on CopyObject). Always `false` with `clientDirectUpload`. * @example `{ copy: true, read: true }` for Cloudflare R2, which documents conditional headers * on GetObject, PutObject and CopyObject only. */ conditional?: boolean | Partial; /** * Configure metafiles storage */ metaStorageConfig?: AwsLightMetaStorageOptions; /** * The parts size that the client should use for presigned multipart unloading. * @default '16MB' */ partSize?: number | string; /** * Sign browser-form POST policies, so `Files.signedUpload` can enforce a size range * (`Files.capabilities.signedUploadPost`). Defaults to `true` for AWS S3 and `false` when a * custom `endpoint` is set: not every S3-compatible service accepts POST uploads (Cloudflare R2 * does not). Set it to `true` for one that does (MinIO, SeaweedFS, …). */ uploadPost?: boolean; }; interface AwsLightError extends Error { code?: string; requestId?: string; statusCode?: number; } /** * AWS Light meta storage implementation using aws4fetch. * Stores each record as the JSON body of an object next to the upload. * Optimized for worker environments (Cloudflare Workers, Web Workers, etc.). */ declare class AwsLightMetaStorage extends MetaStorage { config: AwsLightMetaStorageOptions; /** * Uses `If-Match` conditional writes (S3, R2, MinIO). A service that ignores the header * degrades to plain overwrites, as before. */ override readonly supportsConditionalSave: boolean; private readonly adapter; /** The bucket the records are stored in. */ readonly bucket: string; constructor(config: AwsLightMetaStorageOptions); override get(id: string): Promise; override touch(id: string, file: T): Promise; override delete(id: string): Promise; override save(id: string, file: T): Promise; override saveIfVersion(id: string, file: T, version: string): Promise; private put; } /** * Adapter that uses aws4fetch to implement S3ApiOperations interface. */ declare class AwsLightApiAdapter implements S3ApiOperations { aws: AwsClient; private readonly bucket; /** Bucket URL without a trailing slash; object keys are appended to it. */ private readonly baseUrl; private readonly credentials; constructor(config: AwsLightClientConfig & { bucket: string; }); createMultipartUpload(params: { ACL?: string; Bucket: string; ContentType?: string; Key: string; Metadata?: Record; StorageClass?: string; }, options?: S3CallOptions): Promise<{ UploadId: string; }>; uploadPart(params: { Body: Readable | ReadableStream | Uint8Array; Bucket: string; ContentLength?: number; ContentMD5?: string; Key: string; PartNumber: number; UploadId: string; }, options?: S3CallOptions): Promise<{ ETag: string; }>; uploadPartCopy(params: { Bucket: string; CopySource: string; CopySourceIfMatch?: string; CopySourceRange: string; Key: string; PartNumber: number; UploadId: string; }, options?: S3CallOptions): Promise<{ ETag: string; }>; completeMultipartUpload(params: { Bucket: string; IfMatch?: string; IfNoneMatch?: string; Key: string; Parts: { ETag: string; PartNumber: number; }[]; UploadId: string; }, options?: S3CallOptions): Promise<{ ETag?: string; Location: string; }>; abortMultipartUpload(params: { Bucket: string; Key: string; UploadId: string; }, options?: S3CallOptions): Promise; listMultipartUploads(params: { Bucket: string; KeyMarker?: string; UploadIdMarker?: string; }, options?: S3CallOptions): Promise<{ IsTruncated?: boolean; NextKeyMarker?: string; NextUploadIdMarker?: string; Uploads?: MultipartUpload[]; }>; listParts(params: { Bucket: string; Key: string; PartNumberMarker?: string; UploadId: string; }, options?: S3CallOptions): Promise<{ IsTruncated?: boolean; NextPartNumberMarker?: string; Parts?: Part[]; }>; getObject(params: { Bucket: string; IfMatch?: string; Key: string; Range?: string; }, options?: S3CallOptions): Promise<{ Body?: ReadableStream | Readable; ContentLength?: number; ContentType?: string; ETag?: string; Expires?: Date; LastModified?: Date; Metadata?: Record; }>; headObject(params: { Bucket: string; Key: string; }, options?: S3CallOptions): Promise<{ ContentLength?: number; ContentType?: string; ETag?: string; Expires?: Date; LastModified?: Date; Metadata?: Record; }>; deleteObject(params: { Bucket: string; IfMatch?: string; Key: string; }, options?: S3CallOptions): Promise; copyObject(params: { ACL?: string; Bucket: string; CopySource: string; CopySourceIfMatch?: string; IfMatch?: string; IfNoneMatch?: string; Key: string; StorageClass?: string; }, options?: S3CallOptions): Promise; listObjectsV2(params: { Bucket: string; ContinuationToken?: string; Delimiter?: string; MaxKeys?: number; Prefix?: string; }, options?: S3CallOptions): Promise<{ CommonPrefixes?: { Prefix?: string; }[]; Contents?: { Key?: string; LastModified?: Date; }[]; IsTruncated?: boolean; NextContinuationToken?: string; }>; /** A SigV4 query-signed `PUT` URL for one part, usable without credentials until it expires. */ getPresignedUrl(params: { Bucket: string; expiresIn: number; Key: string; PartNumber: number; UploadId: string; }): Promise; putObject(params: { Body?: Uint8Array | ReadableStream; Bucket: string; ContentLength?: number; ContentType?: string; /** Conditional write: only replace the object while it still has this ETag. */ IfMatch?: string; Key: string; Metadata?: Record; }): Promise<{ ETag?: string; }>; checkBucketAccess(_params: { Bucket: string; }): Promise; /** * Signs a browser-form POST policy for `key` against this bucket's URL. */ presignPost(key: string, options?: UploadPostOptions): UploadPostPolicy; /** * Builds S3 API URL. */ private buildUrl; /** * Converts ReadableStream to Readable for Node.js compatibility. */ private streamToReadable; } /** * AWS Light storage implementation using aws4fetch. * Optimized for worker environments (Cloudflare Workers, Web Workers, etc.). * @example * ```ts * const storage = new AwsLightStorage({ * bucket: , * region: , * accessKeyId: , * secretAccessKey: * }); * ``` * @remarks * ## Worker Compatibility * - Uses aws4fetch for AWS request signing (works in workers) * - No Node.js-specific dependencies * - Compatible with Cloudflare Workers, Web Workers, and edge runtimes * * ## Error Handling * - S3 API errors are normalized with AWS-specific context * - Errors include S3 error codes and status codes for debugging * * ## Retry Behavior * - All S3 API calls are wrapped with configurable retry logic via `retryConfig` option * - Default retryable status codes: 408, 429, 500, 502, 503, 504 (`retryConfig.retryableStatusCodes`) * - A custom `shouldRetry` is consulted first; returning `undefined` defers to the defaults * * ## Multipart Uploads * - Large files are automatically split into multipart uploads * - Maximum 10,000 parts per upload (S3 limitation) * - Part size is configurable (default: 16MB, minimum: 5MB) * - Failed multipart uploads are automatically aborted * * ## Supported Operations * - ✅ create, write, delete, get, getStream, list, update, copy, move * - ✅ Batch operations: deleteBatch, copyBatch, moveBatch (inherited from BaseStorage) * - ✅ exists: Implemented (checks metadata and S3 object) * - ✅ clientDirectUpload: part URLs are SigV4 query-signed (aws4fetch `signQuery`) */ declare class AwsLightStorage extends S3BaseStorage { static override readonly name: string; override readonly storageKind: string; private s3Api; constructor(config: AwsLightStorageOptions); /** * Normalizes AWS S3 errors with S3-specific context. */ override normalizeError(error: AwsLightError | Error): HttpError; override update({ id }: FileQuery, metadata: Partial): Promise; override getStream({ id }: FileQuery, options?: OperationOptions & { range?: { end?: number; start: number; }; }): Promise<{ headers?: Record; size?: number; stream: Readable; }>; override get raw(): AwsClient; override getUploadPost(key: string, options?: UploadPostOptions): Promise; protected getS3Api(): AwsLightApiAdapter; protected getFileClass(): new (config: FileInit) => AwsLightFile; protected getAcl(): string | undefined; protected accessCheck(_maxWaitTime?: number): Promise; } export { type AwsLightClientConfig, type AwsLightError, AwsLightFile, AwsLightMetaStorage, type AwsLightMetaStorageOptions, AwsLightStorage, type AwsLightStorageOptions };