@d3oxy/s3-pilot
Version:
A TypeScript wrapper for AWS S3 and S3-compatible services (R2, MinIO, DigitalOcean Spaces) with a simplified single-client, single-bucket architecture.
270 lines (269 loc) • 11 kB
TypeScript
import type { Readable } from "node:stream";
import { type S3ClientConfigType as AWSConfigType, PutObjectCommand } from "@aws-sdk/client-s3";
/**
* Configuration for S3Pilot instance.
* Each instance represents a single S3 client connected to a single bucket.
*/
export interface S3PilotConfig {
region: string;
accessKeyId: string;
secretAccessKey: string;
bucket: string;
keyPrefix?: string;
additionalConfig?: AWSConfigType;
validateBucketOnInit?: boolean;
/**
* Custom S3-compatible endpoint URL.
* Use this for S3-compatible services like Cloudflare R2, DigitalOcean Spaces, MinIO, etc.
* Example: "https://ACCOUNT_ID.r2.cloudflarestorage.com"
*/
endpoint?: string;
/**
* Base URL for generating public URLs.
* Use this when your files are served from a custom domain, CDN, or R2 public bucket.
* Example: "https://assets.example.com" or "https://pub-xxx.r2.dev"
*/
publicBaseUrl?: string;
}
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;
}
export interface DeleteFilesResponse {
deleted: string[];
errors: Array<{
key: string;
code?: string;
message?: string;
}>;
}
/**
* S3Pilot class abstracts interactions with AWS S3 SDK to provide a cleaner API.
* Each instance represents a single S3 client connected to a single bucket.
*
* Supports S3-compatible services like Cloudflare R2, DigitalOcean Spaces, MinIO, etc.
* via the `endpoint` configuration option.
*/
export declare class S3Pilot {
private readonly s3;
private readonly bucket;
private readonly region;
private readonly keyPrefix?;
private readonly endpoint?;
private readonly publicBaseUrl?;
/**
* Creates an instance of the S3Pilot class.
* @param config - The configuration object for the S3 client and bucket.
*/
constructor(config: S3PilotConfig);
/**
* Validates the bucket on initialization.
* Called from constructor if validateBucketOnInit is true.
* Note: This method is used conditionally in the constructor, which may trigger unused member warnings.
*
* @throws An error if the bucket is not valid or the user does not have access to it.
*/
private validateBucketOnInit;
/**
* Retrieves the URL for a given object key.
*
* URL generation priority:
* 1. If `publicBaseUrl` is configured: `{publicBaseUrl}/{key}`
* 2. If `endpoint` is configured (S3-compatible): `{endpoint}/{bucket}/{key}`
* 3. Default AWS S3 format: `https://{bucket}.s3.{region}.amazonaws.com/{key}`
*
* @param key - The object key.
* @returns The URL of the object.
*/
getUrl(key: string): string;
/**
* Uploads a file stream to the bucket.
*
* @param params - The parameters for the file upload.
* @param params.filename - The name of the file.
* @param params.folder - The folder to upload the file to (optional).
* @param params.stream - The readable stream to upload.
* @param params.contentType - The content type of the file.
* @param params.contentLength - The content length of the stream (optional, but recommended for large files).
* @param params.additionalParams - Additional parameters for the PutObjectCommand (optional).
* @returns A promise that resolves to an object containing the URL, key, etag, and versionId of the uploaded file.
* @throws {Error} If the file fails to upload.
*/
uploadFileStream(params: {
filename: string;
folder?: string;
stream: Readable;
contentType: string;
contentLength?: number;
additionalParams?: Omit<PutObjectCommand, "Bucket" | "Key" | "Body">;
}): Promise<UploadFileStreamResponse>;
/**
* Uploads a file to the bucket.
*
* @param params - The parameters for the file upload.
* @param params.filename - The name of the file.
* @param params.folder - The folder to upload the file to (optional).
* @param params.file - The file to upload.
* @param params.contentType - The content type of the file.
* @param params.additionalParams - Additional parameters for the PutObjectCommand (optional).
* @returns A promise that resolves to an object containing the URL and key of the uploaded file.
* @throws {Error} If the file fails to upload.
*/
uploadFile(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 bucket.
*
* @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(params: {
key: string;
}): Promise<void>;
/**
* Deletes multiple files from the bucket in a single request.
* Automatically batches requests if more than 1000 keys are provided (S3 API limit).
*
* @param params - The parameters for deleting files.
* @param params.keys - Array of keys to delete.
* @returns A promise that resolves to an object containing deleted keys and any errors.
*/
deleteFiles(params: {
keys: string[];
}): Promise<DeleteFilesResponse>;
/**
* Renames a file in the bucket.
*
* @param params - The parameters for renaming the file.
* @param params.oldKey - The key of the file to be renamed.
* @param params.newFolder - The new folder for the renamed file (optional).
* @param params.newFilename - The new filename for the renamed file (optional).
* @returns A promise that resolves to an object containing the URL and key of the renamed file.
* @deprecated This function is not stable and should not be used.
*/
renameFile(params: {
oldKey: string;
newFolder?: string;
newFilename?: string;
}): Promise<{
url: string;
key: string;
}>;
/**
* Moves a file within the bucket from one key to another.
* Uses S3's CopyObject + DeleteObject operations.
*
* @param params - The parameters for moving the file.
* @param params.sourceKey - The current 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.
* @throws {Error} If the file cannot be moved.
*/
moveFile(params: {
sourceKey: string;
destinationKey: string;
}): Promise<UploadFileResponse>;
/**
* Moves a file from this bucket to another bucket.
* First attempts a direct S3 copy (works if same AWS credentials have access to both buckets).
* Falls back to download + upload if direct copy fails (for cross-account moves).
*
* @param params - The parameters for moving the file.
* @param params.sourceKey - The key of the file to move from this bucket.
* @param params.destinationKey - The key for the file in the destination bucket.
* @param params.destination - The destination S3Pilot instance.
* @returns A promise that resolves to an object containing the URL and key of the moved file.
* @throws {Error} If the file cannot be moved.
*/
moveToBucket(params: {
sourceKey: string;
destinationKey: string;
destination: S3Pilot;
}): Promise<UploadFileResponse>;
/**
* 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.
*
* @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(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.
*
* @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(params: {
key: string;
}): Promise<GetFileStreamResponse>;
/**
* Generates a signed URL for accessing an object in the bucket.
* Enhanced version with support for download-specific headers to force browser download
* and avoid CORS issues.
*
* @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(params: {
key: string;
expiresIn?: number;
responseContentDisposition?: string;
responseContentType?: string;
responseCacheControl?: string;
responseContentLanguage?: string;
responseContentEncoding?: string;
responseExpires?: Date;
}): Promise<string>;
/**
* Deletes a folder and all its contents from the bucket.
*
* @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(params: {
folder: string;
}): Promise<void>;
}