Skip to content

Commit

Permalink
feat(s3-client): init package
Browse files Browse the repository at this point in the history
  • Loading branch information
TorinAsakura authored and Nelfimov committed Sep 17, 2024
1 parent 007b0a0 commit bb12229
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 0 deletions.
49 changes: 49 additions & 0 deletions packages/nestjs-s3-client/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"name": "@monstrs/nestjs-s3-client",
"version": "0.1.4",
"license": "MIT",
"type": "module",
"exports": {
"./package.json": "./package.json",
".": "./src/index.ts"
},
"main": "src/index.ts",
"files": [
"dist"
],
"scripts": {
"build": "yarn library build",
"prepack": "yarn run build",
"postpack": "rm -rf dist"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.363.0",
"@aws-sdk/credential-providers": "^3.363.0",
"@aws-sdk/s3-request-presigner": "^3.363.0",
"@aws-sdk/types": "^3.357.0"
},
"devDependencies": {
"@nestjs/common": "^10.0.5",
"@nestjs/core": "^10.0.5",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1"
},
"peerDependencies": {
"@nestjs/common": "^10",
"@nestjs/core": "^10",
"reflect-metadata": "^0.1",
"rxjs": "^7"
},
"publishConfig": {
"exports": {
"./package.json": "./package.json",
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"main": "dist/index.js",
"typings": "dist/index.d.ts"
}
}
4 changes: 4 additions & 0 deletions packages/nestjs-s3-client/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from '@aws-sdk/s3-request-presigner'
export * from '@aws-sdk/client-s3'

export * from './module/index.js'
5 changes: 5 additions & 0 deletions packages/nestjs-s3-client/src/module/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './s3-client.module.interfaces.js'
export * from './s3-client.module.constants.js'
export * from './s3-client.config-factory.js'
export * from './s3-client.factory.js'
export * from './s3-client.module.js'
27 changes: 27 additions & 0 deletions packages/nestjs-s3-client/src/module/s3-client.config-factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { S3ClientConfig } from '@aws-sdk/client-s3'

// eslint-disable-next-line @typescript-eslint/consistent-type-imports
import type { S3ClientModuleOptions } from './s3-client.module.interfaces.js'

import { Inject } from '@nestjs/common'
import { Injectable } from '@nestjs/common'
import { fromEnv } from '@aws-sdk/credential-providers'

import { S3_CLIENT_MODULE_OPTIONS } from './s3-client.module.constants.js'

@Injectable()
export class S3ClientConfigFactory {
constructor(
@Inject(S3_CLIENT_MODULE_OPTIONS)
private readonly options: S3ClientModuleOptions
) {}

createS3ClientOptions(options: S3ClientModuleOptions = {}): S3ClientConfig {
return {
endpoint: options.endpoint || this.options.endpoint || process.env.S3_ENDPOINT,
region: options.region || this.options.region || process.env.S3_REGION,
credentials: options.credentials || this.options.credentials || fromEnv(),
forcePathStyle: true,
}
}
}
15 changes: 15 additions & 0 deletions packages/nestjs-s3-client/src/module/s3-client.factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { S3ClientModuleOptions } from './s3-client.module.interfaces.js'

import { S3Client } from '@aws-sdk/client-s3'
import { Injectable } from '@nestjs/common'

import { S3ClientConfigFactory } from './s3-client.config-factory.js'

@Injectable()
export class S3ClientFactory {
constructor(private readonly configFactory: S3ClientConfigFactory) {}

create(options: S3ClientModuleOptions = {}): S3Client {
return new S3Client(this.configFactory.createS3ClientOptions(options))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const S3_CLIENT_MODULE_OPTIONS = Symbol('s3-client-module-options')
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { AwsCredentialIdentity } from '@aws-sdk/types'
import type { ModuleMetadata } from '@nestjs/common/interfaces'
import type { Type } from '@nestjs/common/interfaces'

export interface S3ClientModuleOptions {
endpoint?: string
region?: string
credentials?: AwsCredentialIdentity
}

export interface S3ClientOptionsFactory {
createS3ClientOptions: () => Promise<S3ClientModuleOptions> | S3ClientModuleOptions
}

export interface S3ClientModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
useExisting?: Type<S3ClientOptionsFactory>
useClass?: Type<S3ClientOptionsFactory>
useFactory?: (...args: Array<any>) => Promise<S3ClientModuleOptions> | S3ClientModuleOptions
inject?: Array<any>
}
72 changes: 72 additions & 0 deletions packages/nestjs-s3-client/src/module/s3-client.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import type { DynamicModule } from '@nestjs/common'
import type { Provider } from '@nestjs/common'

import type { S3ClientModuleOptions } from './s3-client.module.interfaces.js'
import type { S3ClientModuleAsyncOptions } from './s3-client.module.interfaces.js'
import type { S3ClientOptionsFactory } from './s3-client.module.interfaces.js'

import { Module } from '@nestjs/common'

import { S3ClientConfigFactory } from './s3-client.config-factory.js'
import { S3ClientFactory } from './s3-client.factory.js'
import { S3_CLIENT_MODULE_OPTIONS } from './s3-client.module.constants.js'

@Module({})
export class S3ClientModule {
static register(options: S3ClientModuleOptions = {}): DynamicModule {
return {
module: S3ClientModule,
providers: [
S3ClientConfigFactory,
S3ClientFactory,
{
provide: S3_CLIENT_MODULE_OPTIONS,
useValue: options,
},
],
exports: [S3ClientConfigFactory, S3ClientFactory],
}
}

static registerAsync(options: S3ClientModuleAsyncOptions): DynamicModule {
return {
module: S3ClientModule,
imports: options.imports || [],
providers: [...this.createAsyncProviders(options), S3ClientConfigFactory, S3ClientFactory],
exports: [S3ClientConfigFactory, S3ClientFactory],
}
}

private static createAsyncProviders(options: S3ClientModuleAsyncOptions): Array<Provider> {
if (options.useExisting || options.useFactory) {
return [this.createAsyncOptionsProvider(options)]
}

return [
this.createAsyncOptionsProvider(options),
{
provide: options.useClass!,
useClass: options.useClass!,
},
]
}

private static createAsyncOptionsProvider(options: S3ClientModuleAsyncOptions): Provider {
if (options.useFactory) {
return {
provide: S3_CLIENT_MODULE_OPTIONS,
useFactory: options.useFactory,
inject: options.inject || [],
}
}

return {
provide: S3_CLIENT_MODULE_OPTIONS,
useFactory: (
optionsFactory: S3ClientOptionsFactory
): Promise<S3ClientModuleOptions> | S3ClientModuleOptions =>
optionsFactory.createS3ClientOptions(),
inject: [options.useExisting! || options.useClass!],
}
}
}

0 comments on commit bb12229

Please sign in to comment.