Storage
Contract
@modularityjs/storage defines the abstract StorageService:
typescript
abstract class StorageService {
abstract read(key: string): Promise<StorageObject>;
abstract write(
key: string,
data: Buffer | string,
metadata?: WriteMetadata,
): Promise<void>;
abstract delete(key: string): Promise<void>;
abstract exists(key: string): Promise<boolean>;
abstract list(prefix?: string): Promise<StorageEntry[]>;
}Types
typescript
interface StorageObject {
readonly key: string;
readonly size: number;
readonly contentType?: string;
readonly lastModified?: Date;
readonly body: Buffer;
}
interface StorageEntry {
readonly key: string;
readonly size: number;
readonly lastModified?: Date;
}
interface WriteMetadata {
contentType?: string;
}Drivers
Memory (@modularityjs/storage-memory)
Map-based in-memory storage. For development and testing.
typescript
import { StorageModule } from '@modularityjs/core';
import { StorageMemoryModule } from '@modularityjs/storage-memory';
const modules = [StorageModule, StorageMemoryModule];Local Filesystem (@modularityjs/storage-local)
File-based storage using fs/promises. Includes path traversal prevention.
typescript
import { StorageLocalModule } from '@modularityjs/storage-local';
const modules = [
StorageModule,
StorageLocalModule.forRoot({ basePath: './uploads' }),
];S3 (@modularityjs/storage-s3)
AWS S3 and S3-compatible storage (MinIO, Cloudflare R2, DigitalOcean Spaces).
typescript
import { StorageS3Module } from '@modularityjs/storage-s3';
// AWS S3
const modules = [
StorageModule,
StorageS3Module.forRoot({
bucket: 'my-app-uploads',
region: 'eu-west-1',
}),
];
// MinIO / local development
const modules = [
StorageModule,
StorageS3Module.forRoot({
bucket: 'local-bucket',
region: 'us-east-1',
endpoint: 'http://localhost:9000',
credentials: { accessKeyId: 'minioadmin', secretAccessKey: 'minioadmin' },
forcePathStyle: true,
}),
];S3 config options:
| Option | Default | Description |
|---|---|---|
bucket | (required) | S3 bucket name |
region | (required) | AWS region |
endpoint | - | Custom endpoint for S3-compatible services |
credentials | - | Explicit credentials (omit for SDK default chain) |
keyPrefix | '' | Prefix prepended to all object keys |
forcePathStyle | false | Use path-style URLs (required for MinIO) |
Usage
typescript
import { Inject, Injectable, StorageService } from '@modularityjs/core';
@Injectable()
class FileService {
constructor(
@Inject(StorageService) private readonly storage: StorageService,
) {}
async upload(name: string, data: Buffer): Promise<void> {
await this.storage.write(`uploads/${name}`, data, {
contentType: 'application/octet-stream',
});
}
async download(name: string): Promise<Buffer> {
const obj = await this.storage.read(`uploads/${name}`);
return obj.body;
}
async listUploads(): Promise<string[]> {
const entries = await this.storage.list('uploads/');
return entries.map((e) => e.key);
}
}