@nodelabs/nest-aws-s3
v0.0.1
Published
NestJS module for AWS S3
Downloads
57
Readme
@nodelabs/nest-aws-s3
A NestJS dynamic module for interacting with AWS S3 — presigned upload URLs, signed read URLs, URL validation, and raw command execution. Supports both static (forRoot) and async (forRootAsync) configuration, with optional global registration.
Table of Contents
Installation
npm install @nodelabs/nest-aws-s3 @aws-sdk/client-s3 @aws-sdk/s3-request-presignerPeer Dependencies
npm install @nestjs/common @nestjs/config reflect-metadata rxjsOptional peers:
@nestjs/swaggerandclass-validatorare needed only if you use the exported DTOs with Swagger or validation decorators.
Quick Start
// app.module.ts
import { Module } from '@nestjs/common';
import { S3Module } from '@nodelabs/nest-aws-s3';
@Module({
imports: [
S3Module.forRoot({
region: 'us-east-1',
accessKeyId: 'YOUR_ACCESS_KEY_ID',
secretAccessKey: 'YOUR_SECRET_ACCESS_KEY',
bucket: 'my-app-bucket',
}),
],
})
export class AppModule {}Configuration
forRoot (static)
S3Module.forRoot({
region: 'us-east-1',
accessKeyId: 'YOUR_ACCESS_KEY_ID',
secretAccessKey: 'YOUR_SECRET_ACCESS_KEY',
bucket: 'my-app-bucket',
isGlobal: true, // optional
})forRootAsync (factory)
Use forRootAsync to inject configuration from ConfigService or any other provider.
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { S3Module } from '@nodelabs/nest-aws-s3';
@Module({
imports: [
ConfigModule.forRoot(),
S3Module.forRootAsync({
isGlobal: true,
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
region: config.get<string>('AWS_REGION'),
accessKeyId: config.get<string>('AWS_ACCESS_KEY_ID'),
secretAccessKey: config.get<string>('AWS_SECRET_ACCESS_KEY'),
bucket: config.get<string>('AWS_S3_BUCKET'),
}),
}),
],
})
export class AppModule {}Environment variables (example .env)
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key
AWS_S3_BUCKET=my-app-bucketisGlobal
Setting isGlobal: true registers the module globally so AwsS3Service is available across all feature modules without re-importing S3Module.
Available Services
AwsS3Service
import { Injectable } from '@nestjs/common';
import { AwsS3Service } from '@nodelabs/nest-aws-s3';
@Injectable()
export class FileService {
constructor(private readonly s3Service: AwsS3Service) {}
async getUploadUrl(fileName: string, contentType: string) {
return this.s3Service.generateUploadUrl(fileName, contentType);
}
}Methods
| Method | Signature | Description |
|--------|-----------|-------------|
| generateUploadUrl | generateUploadUrl(key: string, contentType: string): Promise<string> | Generates a presigned PUT URL for direct browser-to-S3 uploads. |
| generateSignedReadUrl | generateSignedReadUrl(key: string, expiresIn?: number): Promise<string> | Generates a presigned GET URL for temporary object access. Default expiry is 3600 seconds (1 hour). |
| isS3Url | isS3Url(url: string): boolean | Returns true if the given URL points to the configured S3 bucket. |
| sanitize | sanitize(filePath: string): string | Strips the S3 bucket hostname prefix from a URL, returning the object key only. |
| execute | execute(command: S3Command): Promise<any \| null> | Executes a raw @aws-sdk/client-s3 command. Errors are logged and null is returned on failure. |
generateUploadUrl example
const uploadUrl = await s3Service.generateUploadUrl(
'avatars/user-123.png',
'image/png',
);
// PUT the file directly to `uploadUrl` from the clientgenerateSignedReadUrl example
// Default 1-hour expiry
const readUrl = await s3Service.generateSignedReadUrl('avatars/user-123.png');
// Custom expiry (15 minutes)
const shortUrl = await s3Service.generateSignedReadUrl('avatars/user-123.png', 900);isS3Url / sanitize example
const url = 'https://my-app-bucket.s3.amazonaws.com/avatars/user-123.png';
s3Service.isS3Url(url); // true
s3Service.sanitize(url); // 'avatars/user-123.png'execute (raw command) example
import { HeadObjectCommand } from '@aws-sdk/client-s3';
const meta = await s3Service.execute(
new HeadObjectCommand({ Bucket: 'my-app-bucket', Key: 'avatars/user-123.png' }),
);DTOs
The package exports two DTOs that can be used in your NestJS controllers:
S3UploadRequestDto
| Property | Type | Description |
|----------|------|-------------|
| fileName | string | Original file name requested by the client |
| fileType | string | MIME type of the file (e.g. image/png) |
S3UploadResponseDto
| Property | Type | Description |
|----------|------|-------------|
| url | string | Presigned upload URL |
| requestedName | string | The file name that was requested |
| acceptedType | string | The MIME type that was accepted |
import { Body, Controller, Post } from '@nestjs/common';
import { AwsS3Service, S3UploadRequestDto } from '@nodelabs/nest-aws-s3';
@Controller('files')
export class FilesController {
constructor(private readonly s3Service: AwsS3Service) {}
@Post('upload-url')
async getUploadUrl(@Body() dto: S3UploadRequestDto) {
const url = await this.s3Service.generateUploadUrl(dto.fileName, dto.fileType);
return { url, requestedName: dto.fileName, acceptedType: dto.fileType };
}
}API Reference
IS3ModuleOptions
interface IS3ModuleOptions {
/** AWS region (e.g. 'us-east-1') */
region: string;
/** IAM Access Key ID */
accessKeyId: string;
/** IAM Secret Access Key */
secretAccessKey: string;
/** Target S3 bucket name */
bucket: string;
}IS3ModuleAsyncOptions
interface IS3ModuleAsyncOptions {
/** Register the module globally */
isGlobal?: boolean;
/** NestJS modules to import before the factory runs */
imports?: any[];
/** Providers to inject into useFactory */
inject?: any[];
/** Factory function that returns IS3ModuleOptions */
useFactory: (...args: any[]) => IS3ModuleOptions | Promise<IS3ModuleOptions>;
}Exports
| Symbol | Description |
|--------|-------------|
| S3Module | Dynamic NestJS module (forRoot / forRootAsync) |
| AwsS3Service | Injectable S3 service |
| S3_MODULE_OPTIONS | Injection token for options object |
| IS3ModuleOptions | TypeScript interface for module options |
| IS3ModuleAsyncOptions | TypeScript interface for async options |
| S3UploadRequestDto | DTO for upload-URL request payload |
| S3UploadResponseDto | DTO for upload-URL response payload |
License
MIT
