https://github.com/tacxou/nestjs_module_factorydrive
Factory drive module for NestJS framework
https://github.com/tacxou/nestjs_module_factorydrive
abstract abstraction async bucket disk drive driver factory factorydrive file filesystem nestjs node nodejs npm promise spaces storage
Last synced: 2 months ago
JSON representation
Factory drive module for NestJS framework
- Host: GitHub
- URL: https://github.com/tacxou/nestjs_module_factorydrive
- Owner: tacxou
- License: mit
- Created: 2023-09-18T01:13:44.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2026-03-07T09:52:20.000Z (3 months ago)
- Last Synced: 2026-03-07T09:53:28.758Z (3 months ago)
- Topics: abstract, abstraction, async, bucket, disk, drive, driver, factory, factorydrive, file, filesystem, nestjs, node, nodejs, npm, promise, spaces, storage
- Language: TypeScript
- Homepage: https://www.npmjs.com/package/@tacxou/nestjs_module_factorydrive
- Size: 302 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 11
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Security: SECURITY.md
Awesome Lists containing this project
README
Factory drive module for NestJS framework
## `@tacxou/nestjs_module_factorydrive`
`nestjs_module_factorydrive` provides a simple storage abstraction for NestJS:
- configure one or many disks
- select a default disk
- use built-in local filesystem driver
- register custom drivers (S3, Spaces, etc.)
## Maintained Packages
Current maintained packages in the Factorydrive ecosystem:
- `local`: [`nestjs_module_factorydrive`](https://github.com/tacxou/nestjs_module_factorydrive/blob/main/src/factorydrive/local-file-system.storage.ts)
- `s3`: [`nestjs_module_factorydrive-s3`](https://github.com/tacxou/nestjs_module_factorydrive-s3)
- `sftp`: [`nestjs_module_factorydrive-sftp`](https://github.com/tacxou/nestjs_module_factorydrive-sftp)
## Requirements
- Node.js `>= 22`
- Bun `>= 1.0.0` (used for build/test in this repository)
- NestJS `^6` to `^11` (`@nestjs/common` and `@nestjs/core`)
## Installation
```bash
npm install @tacxou/nestjs_module_factorydrive
```
Or with other package managers:
```bash
yarn add @tacxou/nestjs_module_factorydrive
pnpm add @tacxou/nestjs_module_factorydrive
bun add @tacxou/nestjs_module_factorydrive
```
## Quick Start (synchronous config)
```ts
// app.module.ts
import { Module } from '@nestjs/common'
import { FactorydriveModule } from '@tacxou/nestjs_module_factorydrive'
@Module({
imports: [
FactorydriveModule.forRoot({
default: 'local',
disks: {
local: {
driver: 'local',
config: {
root: `${process.cwd()}/storage`,
},
},
},
}),
],
})
export class AppModule {}
```
## Async Configuration (`forRootAsync`)
```ts
// app.module.ts
import { Module } from '@nestjs/common'
import { ConfigModule, ConfigService } from '@nestjs/config'
import { FactorydriveModule } from '@tacxou/nestjs_module_factorydrive'
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
FactorydriveModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (config: ConfigService) => ({
default: config.get('factorydrive.default', 'local'),
disks: {
local: {
driver: 'local',
config: {
root: config.get('factorydrive.localRoot', `${process.cwd()}/storage`),
},
},
},
}),
}),
],
})
export class AppModule {}
```
## Usage
Inject `FactorydriveService` and interact with a disk instance:
```ts
// file-storage.service.ts
import { Injectable } from '@nestjs/common'
import { FactorydriveService } from '@tacxou/nestjs_module_factorydrive'
@Injectable()
export class FileStorageService {
public constructor(private readonly factorydrive: FactorydriveService) {}
public async uploadFile(path: string, buffer: Buffer): Promise {
await this.factorydrive.getDisk('local').put(path, buffer)
}
public async readFile(path: string): Promise {
const { content } = await this.factorydrive.getDisk('local').get(path)
return content
}
public async deleteFile(path: string): Promise {
const { wasDeleted } = await this.factorydrive.getDisk('local').delete(path)
return wasDeleted
}
}
```
If no disk name is provided, the configured `default` disk is used:
```ts
const disk = this.factorydrive.getDisk()
```
## Built-in Local Driver
The package includes a `local` driver with the following operations:
- `append(location, content)`
- `copy(src, dest)`
- `delete(location)`
- `exists(location)`
- `get(location, encoding?)`
- `getBuffer(location)`
- `getStat(location)`
- `getStream(location)`
- `move(src, dest)`
- `prepend(location, content)`
- `put(location, content)`
- `flatList(prefix?)`
`content` for `put` accepts `Buffer | ReadableStream | string`.
## Register a Custom Driver
Custom drivers must extend `AbstractStorage` and implement the methods you need.
```ts
// aws-s3.storage.ts
import { AbstractStorage, DeleteResponse, Response } from '@tacxou/nestjs_module_factorydrive'
export class AwsS3Storage extends AbstractStorage {
public constructor(private readonly config: { bucket: string }) {
super()
}
public async put(location: string, content: Buffer | NodeJS.ReadableStream | string): Promise {
// Upload implementation...
return { raw: { location, uploaded: true, contentType: typeof content } }
}
public async delete(location: string): Promise {
// Delete implementation...
return { raw: { location }, wasDeleted: true }
}
}
```
Then register it at startup:
```ts
// app.module.ts
import { Module, OnModuleInit } from '@nestjs/common'
import { FactorydriveModule, FactorydriveService } from '@tacxou/nestjs_module_factorydrive'
import { AwsS3Storage } from './aws-s3.storage'
@Module({
imports: [
FactorydriveModule.forRoot({
default: 's3',
disks: {
s3: {
driver: 's3',
config: {
bucket: 'example',
},
},
},
}),
],
})
export class AppModule implements OnModuleInit {
public constructor(private readonly factorydrive: FactorydriveService) {}
public onModuleInit(): void {
this.factorydrive.registerDriver('s3', AwsS3Storage)
}
}
```
## Exported API
Main exports from this package:
- `FactorydriveModule`
- `FactorydriveService`
- `AbstractStorage`
- `StorageManager`
- storage config/types from `factorydrive/types`
- exceptions from `exceptions`
## Error Handling
The module provides dedicated exceptions (for example):
- `InvalidConfigException`
- `DriverNotSupportedException`
- `FileNotFoundException`
- `PermissionMissingException`
- `MethodNotSupportedException`
Catch and map them in your service/controller layers as needed.
## License
MIT