Skip to content

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:

OptionDefaultDescription
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
forcePathStylefalseUse 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);
  }
}