# AWS Nest Module

> AWS SDK Javascript V3 dynamic module for NestJS

## Register

```ts
import { Module } from '@nestjs/common'
import { AppController } from './app.controller'
import { AppService } from './app.service'
import { AwsSdkModule } from '@backend/aws'
import { S3Client } from '@aws-sdk/client-s3'

@Module({
	imports: [
		// register S3 client
		AwsSdkModule.register({
			client: new S3Client({
				region: 'us-west-2',
			}),
		}),
	],
	controllers: [AppController],
	providers: [AppService],
})
export class AppModule {}
```

## Async Register

The library provides an async `useFactory` that allows you to add more logics before setting up the client instance.

```ts
import { S3Client, ListBucketsCommand } from '@aws-sdk/client-s3'
import { AwsSdkModule } from '@backend/aws'

//... your code ...

AwsSdkModule.registerAsync({
	clientType: S3Client,
	useFactory: async () => {
		const s3 = new S3Client({
			region: 'us-west-2',
		})

		try {
			const listCommand = new ListBucketsCommand({})
			const res = await s3.send(listCommand)
			console.log('Connected to S3')
		} catch (e) {
			console.log('Unable to connect to S3', e)
		}

		return s3
	},
})
```

### Use `@InjectAws(Client)`

With a registered S3 client, you can now inject the instance to your service and controller.

> Make sure the `Client` is the type you registered in module.

```ts
/** Use S3 client in AppController */
import { ListBucketsCommand, S3Client } from '@aws-sdk/client-s3'
import { Controller, Get } from '@nestjs/common'
import { AppService } from './app.service'
import { InjectAws } from '@backend/aws'

@Controller()
export class AppController {
	constructor(
		private readonly appService: AppService,
		@InjectAws(S3Client) private readonly s3: S3Client,
	) {}
	@Get()
	async helloAws() {
		const listCommand = new ListBucketsCommand({})
		const res = await this.s3.send(listCommand)
		return res
	}
}
```

## Multiple Injection/Instances

To add more instances is easy, just `register` more!
If you have same type of clients, please use the `key` attribute as the identifier.

Example for multiple S3 client instances

### Register the S3 Client with a unique `key`

```ts
AwsSdkModule.register({
  // register the S3 Client with key `US-WEST-2-CLIENT`
  key: 'US-WEST-2-CLIENT',
  client: new S3Client({
    region: 'us-west-2',
  }),
}),
AwsSdkModule.register({
  // register the S3 Client with key `US-EAST-1-CLIENT`
  key: 'US-EAST-1-CLIENT',
  client: new S3Client({
    region: 'us-east-1',
  }),
}),
```

### Inject and refer clients by `@InjectAws(Client, key)`

```ts
@InjectAws(S3Client, "US-WEST-2-CLIENT") private readonly s3west2: S3Client,
@InjectAws(S3Client, "US-EAST-1-CLIENT") private readonly s3east1: S3Client,
```

## Global Module

By default, a client is only available at where it is registered.
You have an option to make it global, `isGlobal: true`

```ts
AwsSdkModule.register({
	isGlobal: true,
	client: new S3Client({
		region: 'us-west-2',
	}),
})
```

## Get client token

If you need a client key for testing purpose. Please pass the [AWS SDK V3 client](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/index.html) and `key` to `getClientToken`

```ts
getClientToken(S3Client, (key = ''))
```
