S3 driver for Factory drive module from NestJS framework
S3 storage driver for @ficsysfr/nestjs_module_factorydrive, built for NestJS.
- Amazon S3-compatible implementation of
AbstractStorage - Common file operations (
put,get,copy,move,delete,exists) - Stream and buffer support for downloads/uploads
- Signed URL generation via AWS SDK v3
- Flat listing with automatic pagination (
listObjectsV2) - Domain exceptions mapping from S3 errors
- Node.js
>= 22 - Bun
>= 1(for local scripts/tests in this repository) - A configured S3 bucket (AWS S3 or S3-compatible endpoint)
Install the Factory Drive core module and this S3 driver:
npm install @ficsysfr/nestjs_module_factorydrive @ficsysfr/nestjs_module_factorydrive-s3yarn add @ficsysfr/nestjs_module_factorydrive @ficsysfr/nestjs_module_factorydrive-s3pnpm add @ficsysfr/nestjs_module_factorydrive @ficsysfr/nestjs_module_factorydrive-s3bun add @ficsysfr/nestjs_module_factorydrive @ficsysfr/nestjs_module_factorydrive-s3Register the driver class in your app startup:
import { Module } from '@nestjs/common'
import { FactorydriveService } from '@ficsysfr/nestjs_module_factorydrive'
import { AwsS3Storage } from '@ficsysfr/nestjs_module_factorydrive-s3'
@Module({
// ...
})
export class AppModule {
public constructor(storage: FactorydriveService) {
storage.registerDriver('s3', AwsS3Storage)
}
}The constructor accepts AmazonWebServicesS3StorageConfig, which extends AWS S3ClientConfig and adds:
bucket(string, required): target bucket name
Example:
import { AwsS3Storage } from '@ficsysfr/nestjs_module_factorydrive-s3'
const storage = new AwsS3Storage({
bucket: 'my-app-bucket',
region: 'eu-west-1',
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
},
})For S3-compatible providers (MinIO, DigitalOcean Spaces, Backblaze B2, Cloudflare R2, etc.), pass your custom endpoint/options through standard AWS SDK S3ClientConfig. Do not hardcode provider-specific options in the driver — leave them to the consumer via config.
B2 often requires disabling AWS SDK v3 flexible checksums on put/get. Pass them through S3ClientConfig:
const storage = new AwsS3Storage({
bucket: 'my-b2-bucket',
region: 'us-west-004',
endpoint: 'https://s3.us-west-004.backblazeb2.com',
credentials: {
accessKeyId: process.env.B2_KEY_ID!,
secretAccessKey: process.env.B2_APPLICATION_KEY!,
},
requestChecksumCalculation: 'WHEN_REQUIRED',
responseChecksumValidation: 'WHEN_REQUIRED',
})These checksum options are optional and should not be set for real AWS S3 unless you have a specific need.
put(location, content): upload string,Buffer, or readable streamcopy(src, dest): copy object within the bucketmove(src, dest): copy then delete sourcedelete(location): delete object (wasDeletedisnull, raw response is exposed)
get(location, encoding?): returns file content as textgetBuffer(location): returns file content asBuffergetStream(location): returns a readable streamgetStat(location): returns{ size, modified, raw }exists(location): checks object existenceflatList(prefix?): async iterator over all object keys (paginated)getSignedUrl(location, options?): temporary signed GET URL (defaultexpiresIn = 900seconds)
Known S3 errors are converted into Factory Drive exceptions:
NoSuchBucket->NoSuchBucketExceptionNoSuchKey->FileNotFoundExceptionAllAccessDisabled->PermissionMissingException- any other error ->
UnknownException
This keeps error handling consistent with the rest of the Factory Drive ecosystem.
await storage.put('documents/invoice.txt', 'hello world')
const { exists } = await storage.exists('documents/invoice.txt')
if (exists) {
const file = await storage.get('documents/invoice.txt')
console.log(file.content)
}
const signed = await storage.getSignedUrl('documents/invoice.txt', { expiresIn: 60 })
console.log(signed.signedUrl)Useful scripts:
yarn lint: run Biome checksyarn typecheck: typecheck without emitting filesyarn test: run Vitest testsyarn test:coverage: run tests with enforced coverage thresholdsyarn build: build the packageyarn package/make package: create and audit the npm tarball under.artifacts/npm/make check: run every local quality gatemake release VERSION=2.0.0 CHANNEL=latest WATCH=1: dispatch and optionally watch the manual release
CI runs tests (with coverage upload) and build on pushes/PRs.
- Peer dependency:
@ficsysfr/nestjs_module_factorydrive@^2.0.0 - TypeScript peer dependency:
^5.0.0
Please read SECURITY.md before reporting vulnerabilities.
MIT, see LICENSE.