UNPKG

@d3oxy/s3-pilot

Version:

A TypeScript wrapper for AWS S3 with support for multiple clients, buckets, and secure file downloads.

280 lines (279 loc) 13.6 kB
import { S3ClientConfigType as AWSConfigType, PutObjectCommand, S3Client } from "@aws-sdk/client-s3"; import { Readable } from "stream"; /** * Type for configuring an individual S3 client. * @template BucketNames - Bucket names for the client. */ export type S3ClientSettings<BucketNames extends string> = { region: string; accessKeyId: string; secretAccessKey: string; buckets: BucketNames[]; keyPrefix?: string; additionalConfig?: AWSConfigType; enableDefaultAllowedExtensions?: boolean; allowedExtensions?: string[]; validateBucketOnInit?: boolean; }; /** * Type for setting up multiple S3 clients. * @template Clients - Record of client names to their configurations. */ export type S3ClientsSetup<Clients extends Record<string, S3ClientSettings<string>>> = Clients; export interface UploadFileResponse { url: string; key: string; } export interface UploadFileStreamResponse extends UploadFileResponse { etag?: string; versionId?: string; } export interface GetFileResponse { buffer: Buffer; contentType?: string; contentLength?: number; etag?: string; lastModified?: Date; } export interface GetFileStreamResponse { stream: Readable; contentType?: string; contentLength?: number; etag?: string; lastModified?: Date; } /** * S3Pilot class abstracts interactions with AWS S3 SDK to provide a cleaner API. * @template Clients - Mapping of client names to their configurations. */ export declare class S3Pilot<Clients extends Record<string, S3ClientSettings<string>>> { /** * Represents the client instances for different clients. */ private clientInstances; /** * Creates an instance of the S3Pilot class. * @param config - The configuration object for setting up S3 clients. */ constructor(config: S3ClientsSetup<Clients>); /** * Retrieves the URL for a given object key in a specific bucket of a client. * @param clientName - The name of the client. * @param bucket - The bucket object from the client. * @param key - The object key. * @returns A promise that resolves to the URL of the object. */ getUrl<ClientName extends keyof Clients>(clientName: ClientName, bucket: Clients[ClientName]["buckets"][number], key: string): Promise<string>; /** * Validates the specified bucket on initialization. * * @param client - The S3 client. * @param bucket - The name of the bucket to validate. * @throws An error if the bucket is not valid or the user does not have access to it. */ private validateBucketOnInit; /** * Validates if a bucket is available for a given client. * * @template ClientName - The name of the client. * @param clientName - The name of the client. * @param bucket - The bucket to validate. * @throws {Error} If the bucket is not available for the client. */ private validateBucket; private validateExtension; /** * Retrieves the client instance for the specified client name. * * @template ClientName - The type of the client name. * @param {ClientName} clientName - The name of the client. * @returns {Object} - An object containing the S3 client, a set of buckets, and an optional key prefix. */ getClient<ClientName extends keyof Clients>(clientName: ClientName): { s3: S3Client; buckets: Set<string>; keyPrefix?: string; region: string; enableDefaultAllowedExtensions?: boolean; allowedExtensions?: string[]; }; /** * Uploads a file stream to the specified bucket for the given client. * * @template ClientName - The name of the client. * @param {ClientName} clientName - The name of the client. * @param {Clients[ClientName]["buckets"][number]} bucket - The bucket to upload the file to. * @param {Object} params - The parameters for the file upload. * @param {string} params.filename - The name of the file. * @param {string} [params.folder] - The folder to upload the file to (optional). * @param {Readable} params.stream - The readable stream to upload. * @param {string} params.contentType - The content type of the file. * @param {number} [params.contentLength] - The content length of the stream (optional, but recommended for large files). * @param {Omit<PutObjectCommand, "Bucket" | "Key" | "Body">} [params.additionalParams] - Additional parameters for the PutObjectCommand (optional). * @returns {Promise<UploadFileStreamResponse>} A promise that resolves to an object containing the URL, key, etag, and versionId of the uploaded file. * @throws {Error} If the file extension is invalid or if the file fails to upload. */ uploadFileStream<ClientName extends keyof Clients>(clientName: ClientName, bucket: Clients[ClientName]["buckets"][number], params: { filename: string; folder?: string; stream: Readable; contentType: string; contentLength?: number; additionalParams?: Omit<PutObjectCommand, "Bucket" | "Key" | "Body">; }): Promise<UploadFileStreamResponse>; /** * Uploads a file to the specified bucket for the given client. * * @template ClientName - The name of the client. * @param {ClientName} clientName - The name of the client. * @param {Clients[ClientName]["buckets"][number]} bucket - The bucket to upload the file to. * @param {Object} params - The parameters for the file upload. * @param {string} params.filename - The name of the file. * @param {string} [params.folder] - The folder to upload the file to (optional). * @param {Buffer | Uint8Array | Blob | string} params.file - The file to upload. * @param {string} params.contentType - The content type of the file. * @param {Omit<PutObjectCommand, "Bucket" | "Key" | "Body">} [params.additionalParams] - Additional parameters for the PutObjectCommand (optional). * @returns {Promise<UploadFileResponse>} A promise that resolves to an object containing the URL and key of the uploaded file. * @throws {Error} If the file extension is invalid or if the file fails to upload. */ uploadFile<ClientName extends keyof Clients>(clientName: ClientName, bucket: Clients[ClientName]["buckets"][number], params: { filename: string; folder?: string; file: Buffer | Uint8Array | Blob | string; contentType: string; additionalParams?: Omit<PutObjectCommand, "Bucket" | "Key" | "Body">; }): Promise<UploadFileResponse>; /** * Deletes a file from the specified bucket. * * @param clientName - The name of the client. * @param bucket - The bucket from which to delete the file. * @param params - The parameters for deleting the file. * @param params.key - The key of the file to delete. * @returns A Promise that resolves when the file is successfully deleted. */ deleteFile<ClientName extends keyof Clients>(clientName: ClientName, bucket: Clients[ClientName]["buckets"][number], params: { key: string; }): Promise<void>; /** * Renames a file in the specified bucket of a client. * * @template ClientName - The name of the client. * @param {ClientName} clientName - The name of the client. * @param {Clients[ClientName]["buckets"][number]} bucket - The bucket in which the file is located. * @param {Object} params - The parameters for renaming the file. * @param {string} params.oldKey - The key of the file to be renamed. * @param {string} [params.newFolder] - The new folder for the renamed file (optional). * @param {string} [params.newFilename] - The new filename for the renamed file (optional). * @returns {Promise<{ * url: string; * key: string; * acl: ObjectCannedACL; * }>} - A promise that resolves to an object containing the URL, key, and ACL of the renamed file. * @deprecated This function is not stable and should not be used. */ renameFile<ClientName extends keyof Clients>(clientName: ClientName, bucket: Clients[ClientName]["buckets"][number], params: { oldKey: string; newFolder?: string; newFilename?: string; }): Promise<{ url: string; key: string; }>; /** * Downloads a file from S3 and returns its content as a Buffer. * This method is useful for server-side file processing or when you need to * stream file content to clients through your API server. * * @template ClientName - The name of the client. * @param clientName - The name of the client. * @param bucket - The bucket containing the file. * @param params - The parameters for downloading the file. * @param params.key - The key of the file to download. * @returns A promise that resolves to an object containing the file buffer and metadata. * @throws {Error} If the file cannot be downloaded or doesn't exist. */ getFile<ClientName extends keyof Clients>(clientName: ClientName, bucket: Clients[ClientName]["buckets"][number], params: { key: string; }): Promise<GetFileResponse>; /** * Downloads a file from S3 and returns its content as a readable stream. * This method is useful for streaming large files efficiently without loading * the entire file into memory. * * @template ClientName - The name of the client. * @param clientName - The name of the client. * @param bucket - The bucket containing the file. * @param params - The parameters for downloading the file. * @param params.key - The key of the file to download. * @returns A promise that resolves to an object containing the file stream and metadata. * @throws {Error} If the file cannot be downloaded or doesn't exist. */ getFileStream<ClientName extends keyof Clients>(clientName: ClientName, bucket: Clients[ClientName]["buckets"][number], params: { key: string; }): Promise<GetFileStreamResponse>; /** * Generates a signed URL for accessing an object in a specific bucket of a client. * Enhanced version with support for download-specific headers to force browser download * and avoid CORS issues. * * @param clientName - The name of the client. * @param bucket - The bucket to generate the signed URL for. * @param params - Additional parameters for generating the signed URL. * @param params.key - The key of the object. * @param params.expiresIn - The expiration time of the signed URL in seconds. Defaults to 1 hour (3600 seconds). * @param params.responseContentDisposition - Optional content disposition header to force download behavior. * @param params.responseContentType - Optional content type header. * @param params.responseCacheControl - Optional cache control header. * @param params.responseContentLanguage - Optional content language header. * @param params.responseContentEncoding - Optional content encoding header. * @param params.responseExpires - Optional expires header. * @returns A promise that resolves to the signed URL. */ generateSignedUrl<ClientName extends keyof Clients>(clientName: ClientName, bucket: Clients[ClientName]["buckets"][number], params: { key: string; expiresIn?: number; responseContentDisposition?: string; responseContentType?: string; responseCacheControl?: string; responseContentLanguage?: string; responseContentEncoding?: string; responseExpires?: Date; }): Promise<string>; /** * Extracts the key from the given URL. * @param url - The URL from which to extract the key. * @returns A Promise that resolves to the extracted key. * @throws An error if the URL is invalid or the key cannot be extracted. */ getKeyFromUrl(url: string): Promise<string>; /** * Moves a file from one key to another, possibly across buckets, for the given client. * * @template ClientName - The name of the client. * @param clientName - The name of the client. * @param sourceBucket - The source bucket. * @param destinationBucket - The destination bucket. * @param params - The parameters for moving the file. * @param params.sourceKey - The key of the file to move. * @param params.destinationKey - The new key for the file. * @returns A promise that resolves to an object containing the URL and key of the moved file. */ moveFile<ClientName extends keyof Clients>(clientName: ClientName, sourceBucket: Clients[ClientName]["buckets"][number], destinationBucket: Clients[ClientName]["buckets"][number], params: { sourceKey: string; destinationKey: string; }): Promise<UploadFileResponse>; /** * Deletes a folder and all its contents from the specified bucket. * * @template ClientName - The name of the client. * @param clientName - The name of the client. * @param bucket - The bucket from which to delete the folder. * @param params - The parameters for deleting the folder. * @param params.folder - The folder to delete. * @returns A promise that resolves when the folder and its contents are successfully deleted. */ deleteFolder<ClientName extends keyof Clients>(clientName: ClientName, bucket: Clients[ClientName]["buckets"][number], params: { folder: string; }): Promise<void>; }