Nest: [Feature] NestJS AWS S3 Wrapper

Created on 26 Jul 2020  路  3Comments  路  Source: nestjs/nest

Feature Request

NestJS AWS S3 Wrapper

Is your feature request related to a problem? Please describe.


TBA

Describe the solution you'd like


TBA

Teachability, Documentation, Adoption, Migration Strategy


TBA

What is the motivation / use case for changing the behavior?


TBA

needs triage type

Most helpful comment

@unckleg You can create your own AWS module in Nest so you can have more flexibility when it comes to customize your function. Here is an example,

For more: https://docs.nestjs.com/modules

aws.ts

import { Logger } from '@nestjs/common';
import * as AWS from 'aws-sdk';

import { AWSConfig } from './aws.dto';

export class AWSLib {
  public s3: AWS.S3;
  public ses: AWS.SES;
  public sns: AWS.SNS;

  private logger: Logger = new Logger('AWSModule');

  constructor(public readonly config: AWSConfig) {
    AWS.config.update({
      accessKeyId: config.AWS_ACCESS_KEY_ID,
      secretAccessKey: config.AWS_SECRET_ACCESS_KEY,
      region: config.AWS_REGION
    });

    this.s3 = new AWS.S3();
    this.ses = new AWS.SES();
    this.sns = new AWS.SNS();
    this.logger.log('AWS loaded');
  }
}

aws.constant.ts

export const AWS_TOKEN = 'AWS_INJECT_TOKEN';

aws.decorator.ts

import { Inject } from '@nestjs/common';
import { AWS_TOKEN } from './aws.constant';

export const InjectAWS = () => Inject(AWS_TOKEN);

aws.dto.ts

import { IsNotEmpty, IsOptional, IsString } from 'class-validator';

export class AWSConfig {
  @IsNotEmpty()
  @IsString()
  AWS_ACCESS_KEY_ID!: string;

  @IsNotEmpty()
  @IsString()
  AWS_SECRET_ACCESS_KEY!: string;

  @IsNotEmpty()
  @IsString()
  AWS_REGION!: string;

  @IsNotEmpty()
  @IsString()
  AWS_S3_BUCKET!: string;

  @IsNotEmpty()
  @IsString()
  AWS_S3_PREFIX!: string;
}

aws.module.ts

import { Global, Module } from '@nestjs/common';

import { AWSProvider } from './aws.provider';

@Global()
@Module({
  providers: [AWSProvider],
  exports: [AWSProvider]
})
export class AWSModule {}

aws.provider.ts

import { ConfigService } from '../config';
import { AWSLib } from './aws';
import { AWS_TOKEN } from './aws.constant';
import { AWSConfig } from './aws.dto';

export const AWSProvider = {
  inject: [ConfigService],
  provide: AWS_TOKEN,
  useFactory: (configService: ConfigService) => {
    const config = configService.validate('AWSModule', AWSConfig);
    return new AWSLib(config);
  }
};

app.module.ts

import { Module } from '@nestjs/common';
import { AWSModule } from '@lib/aws';

@Module({
  imports: [
    AWSModule
  ]
})
export class ApplicationModule {}

example.service.ts

@Injectable()
export class ExampleService {
  constructor(@InjectAWS() private readonly aws: AWSLib) {}
}

All 3 comments

@unckleg You can create your own AWS module in Nest so you can have more flexibility when it comes to customize your function. Here is an example,

For more: https://docs.nestjs.com/modules

aws.ts

import { Logger } from '@nestjs/common';
import * as AWS from 'aws-sdk';

import { AWSConfig } from './aws.dto';

export class AWSLib {
  public s3: AWS.S3;
  public ses: AWS.SES;
  public sns: AWS.SNS;

  private logger: Logger = new Logger('AWSModule');

  constructor(public readonly config: AWSConfig) {
    AWS.config.update({
      accessKeyId: config.AWS_ACCESS_KEY_ID,
      secretAccessKey: config.AWS_SECRET_ACCESS_KEY,
      region: config.AWS_REGION
    });

    this.s3 = new AWS.S3();
    this.ses = new AWS.SES();
    this.sns = new AWS.SNS();
    this.logger.log('AWS loaded');
  }
}

aws.constant.ts

export const AWS_TOKEN = 'AWS_INJECT_TOKEN';

aws.decorator.ts

import { Inject } from '@nestjs/common';
import { AWS_TOKEN } from './aws.constant';

export const InjectAWS = () => Inject(AWS_TOKEN);

aws.dto.ts

import { IsNotEmpty, IsOptional, IsString } from 'class-validator';

export class AWSConfig {
  @IsNotEmpty()
  @IsString()
  AWS_ACCESS_KEY_ID!: string;

  @IsNotEmpty()
  @IsString()
  AWS_SECRET_ACCESS_KEY!: string;

  @IsNotEmpty()
  @IsString()
  AWS_REGION!: string;

  @IsNotEmpty()
  @IsString()
  AWS_S3_BUCKET!: string;

  @IsNotEmpty()
  @IsString()
  AWS_S3_PREFIX!: string;
}

aws.module.ts

import { Global, Module } from '@nestjs/common';

import { AWSProvider } from './aws.provider';

@Global()
@Module({
  providers: [AWSProvider],
  exports: [AWSProvider]
})
export class AWSModule {}

aws.provider.ts

import { ConfigService } from '../config';
import { AWSLib } from './aws';
import { AWS_TOKEN } from './aws.constant';
import { AWSConfig } from './aws.dto';

export const AWSProvider = {
  inject: [ConfigService],
  provide: AWS_TOKEN,
  useFactory: (configService: ConfigService) => {
    const config = configService.validate('AWSModule', AWSConfig);
    return new AWSLib(config);
  }
};

app.module.ts

import { Module } from '@nestjs/common';
import { AWSModule } from '@lib/aws';

@Module({
  imports: [
    AWSModule
  ]
})
export class ApplicationModule {}

example.service.ts

@Injectable()
export class ExampleService {
  constructor(@InjectAWS() private readonly aws: AWSLib) {}
}

Let's remove all core modules and develop them by ourselves. (For all projects).

@Dominic-Preap You can create a PR if you want 馃槈

The idea of Nest is that the framework is supposed to be extensible by anyone, not just the core team and maintainers. I'm with @Dominic-Preap on this one, and would personally leave it to the community to make a module for this, otherwise Nest will be expected to maintain modules for AWS, Azure, GCP, and anything that shows up in the future, which simply isn't maintainable.

Was this page helpful?
0 / 5 - 0 ratings