From d4f6a823c0bef6a24cf01670f3aa3c8cd9731739 Mon Sep 17 00:00:00 2001 From: Kerry Ritter Date: Fri, 26 Jan 2024 10:37:41 -0600 Subject: [PATCH] bugfix(typescript-v5) fixing decorator returntype for v5 --- README.md | 53 ++++--- package-lock.json | 235 ++++++++++++++++++++++++++----- package.json | 2 +- src/lib/aws-service.decorator.ts | 2 +- 4 files changed, 228 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 6a23a06..35dd211 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@
- A thin wrapping layer around the aws-sdk package for clean NestJS dependency injection. + A thin wrapping layer around the aws-sdk (AWS SDK v2) package for clean NestJS dependency injection.

@@ -15,10 +15,10 @@ # Features -* Decorator for injecting AWS services. -* An AWS service factory for on-the-fly AWS client creation. -* A simple dependency injection model with AwsSdkModule.forRootAsync() and AwsSdkModule.forFeature(). -* Helper test tools for creating mocked AWS clients. +- Decorator for injecting AWS services. +- An AWS service factory for on-the-fly AWS client creation. +- A simple dependency injection model with AwsSdkModule.forRootAsync() and AwsSdkModule.forFeature(). +- Helper test tools for creating mocked AWS clients. # How To Use @@ -80,10 +80,7 @@ import { S3 } from 'aws-sdk'; @Injectable() export class S3ManagerService { - constructor( - @InjectAwsService(S3) private readonly s3: S3, - ) { - } + constructor(@InjectAwsService(S3) private readonly s3: S3) {} async listBucketContents(bucket: string) { const response = await this.s3.listObjectsV2({ Bucket: bucket }).promise(); @@ -96,7 +93,11 @@ export class S3ManagerService { // s3-manager.service.spec.ts import { Test, TestingModule } from '@nestjs/testing'; import { S3 } from 'aws-sdk'; -import { createAwsServiceMock, createAwsServicePromisableSpy, getAwsServiceMock } from 'nest-aws-sdk/dist/testing'; +import { + createAwsServiceMock, + createAwsServicePromisableSpy, + getAwsServiceMock, +} from 'nest-aws-sdk/dist/testing'; import { S3ManagerService } from './s3-manager.service'; describe('S3ManagerService', () => { @@ -108,19 +109,19 @@ describe('S3ManagerService', () => { createAwsServiceMock(S3, { useValue: { listObjectsV2: () => null, - } + }, }), ], }).compile(); const service = module.get(S3ManagerService); - + const listSpy = createAwsServicePromisableSpy( getAwsServiceMock(module, S3), 'listObjectsV2', 'resolve', { - Contents: [ { Key: 'myKey' } ], + Contents: [{ Key: 'myKey' }], }, ); @@ -131,7 +132,7 @@ describe('S3ManagerService', () => { expect(listSpy).toHaveBeenCalledTimes(1); expect(listSpy).toHaveBeenCalledWith({ Bucket: 'myBucket' }); }); - }) + }); }); ``` @@ -157,7 +158,7 @@ import { S3ManagerModule } from './s3-manager/s3-manager.module'; credentials: new SharedIniFileCredentials({ profile: 'my-profile', }), - } + }, }, }), ], @@ -211,8 +212,8 @@ import { CloudFront, S3, SharedIniFileCredentials } from 'aws-sdk'; credentials: new SharedIniFileCredentials({ profile: 'aws-nest-sdk', }), - } - } + }, + }, ], }), ], @@ -237,10 +238,7 @@ import { AwsSdkModule } from 'nest-aws-sdk'; import { S3ManagerModule } from './s3-manager/s3-manager.module'; @Module({ - imports: [ - S3ManagerModule, - AwsSdkModule.forRootAsync(), - ], + imports: [S3ManagerModule, AwsSdkModule.forRootAsync()], providers: [], exports: [], }) @@ -269,7 +267,7 @@ import { S3ManagerModule } from './s3-manager/s3-manager.module'; credentials: new SharedIniFileCredentials({ profile: 'my-profile', }), - } + }, }, }), ], @@ -311,13 +309,13 @@ import { ConfigService, ConfigModule } from './config'; ## AwsSdkModule.forFeatures() -`AwsSdkModule.forFeatures()` creates the providers for the AWS clients you wish to use at a module-specific level. +`AwsSdkModule.forFeatures()` creates the providers for the AWS clients you wish to use at a module-specific level. **Note: forFeatures cannot be used in combination with root-level service registrations.** ### Basic usage -To provide clients to the module context, pass the client constructor symbol to the `AwsSdkModule.forFeatures()` method. Note, it is best to import the client directly from `aws-sdk` instead of from deeper paths - the deeper paths may produce unexpected behaviors. +To provide clients to the module context, pass the client constructor symbol to the `AwsSdkModule.forFeatures()` method. Note, it is best to import the client directly from `aws-sdk` instead of from deeper paths - the deeper paths may produce unexpected behaviors. ```ts import { Module } from '@nestjs/common'; @@ -366,13 +364,12 @@ const module: TestingModule = await Test.createTestingModule({ createAwsServiceMock(S3, { useValue: { listObjectsV2: () => null, - } + }, }), ], }).compile(); ``` - ### getAwsServiceMock To retrieve a mock from the test bed via the correct symbol, `getAwsServiceMock` is exported. @@ -391,7 +388,7 @@ it('should call the list method and return the Content keys', async () => { s3, // the mocked object to spy on 'listObjectsV2', // the method to spy on 'resolve', // 'resolve' or 'reject' - { Contents: [ { Key: 'myKey' } ] }, // the value to resolve or reject + { Contents: [{ Key: 'myKey' }] }, // the value to resolve or reject ); const result = await service.listBucketContents('myBucket'); @@ -405,7 +402,7 @@ it('should call the list method and return the Content keys', async () => { # Stay In Touch -* Author - [Kerry Ritter](https://twitter.com/kerryritter) and BeerMoneyDev +- Author - [Kerry Ritter](https://twitter.com/kerryritter) and BeerMoneyDev ## License diff --git a/package-lock.json b/package-lock.json index 31ba9a9..e316d88 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "@types/aws-sdk": "^2.7.0", "@types/express": "^4.17.3", "@types/jest": "25.2.3", - "@types/node": "^14.18.22", + "@types/node": "^14.18.63", "@types/superagent": "^4.1.15", "@types/supertest": "^2.0.12", "@typescript-eslint/eslint-plugin": "^5", @@ -1600,6 +1600,19 @@ "node": ">= 12.9.0" } }, + "node_modules/@nestjs/cli/node_modules/typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/@nestjs/common": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-9.0.3.tgz", @@ -1694,19 +1707,105 @@ } }, "node_modules/@nestjs/schematics": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-9.0.1.tgz", - "integrity": "sha512-QU7GbnQvADFXdumcdADmv4vil3bhnYl2IFHWKieRt0MgIhghgBxIB7kDKWhswcuZ0kZztVbyYjo9aCrlf62fcw==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-9.2.0.tgz", + "integrity": "sha512-wHpNJDPzM6XtZUOB3gW0J6mkFCSJilzCM3XrHI1o0C8vZmFE1snbmkIXNyoi1eV0Nxh1BMymcgz5vIMJgQtTqw==", "dev": true, "dependencies": { - "@angular-devkit/core": "14.0.5", - "@angular-devkit/schematics": "14.0.5", - "fs-extra": "10.1.0", - "jsonc-parser": "3.0.0", + "@angular-devkit/core": "16.0.1", + "@angular-devkit/schematics": "16.0.1", + "jsonc-parser": "3.2.0", "pluralize": "8.0.0" }, "peerDependencies": { - "typescript": "^4.3.5" + "typescript": ">=4.3.5" + } + }, + "node_modules/@nestjs/schematics/node_modules/@angular-devkit/core": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.0.1.tgz", + "integrity": "sha512-2uz98IqkKJlgnHbWQ7VeL4pb+snGAZXIama2KXi+k9GsRntdcw+udX8rL3G9SdUGUF+m6+147Y1oRBMHsO/v4w==", + "dev": true, + "dependencies": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@nestjs/schematics/node_modules/@angular-devkit/schematics": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.0.1.tgz", + "integrity": "sha512-A9D0LTYmiqiBa90GKcSuWb7hUouGIbm/AHbJbjL85WLLRbQA2PwKl7P5Mpd6nS/ZC0kfG4VQY3VOaDvb3qpI9g==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "16.0.1", + "jsonc-parser": "3.2.0", + "magic-string": "0.30.0", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@nestjs/schematics/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@nestjs/schematics/node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "node_modules/@nestjs/schematics/node_modules/magic-string": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", + "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@nestjs/schematics/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" } }, "node_modules/@nestjs/testing": { @@ -2453,9 +2552,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "14.18.22", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.22.tgz", - "integrity": "sha512-qzaYbXVzin6EPjghf/hTdIbnVW1ErMx8rPzwRNJhlbyJhu2SyqlvjGOY/tbUt6VFyzg56lROcOeSQRInpt63Yw==", + "version": "14.18.63", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", + "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -12713,9 +12812,9 @@ } }, "node_modules/rxjs": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz", - "integrity": "sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dev": true, "dependencies": { "tslib": "^2.1.0" @@ -14177,9 +14276,9 @@ "dev": true }, "node_modules/typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -15984,6 +16083,14 @@ "typescript": "4.7.4", "webpack": "5.73.0", "webpack-node-externals": "3.0.0" + }, + "dependencies": { + "typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true + } } }, "@nestjs/common": { @@ -16026,16 +16133,76 @@ } }, "@nestjs/schematics": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-9.0.1.tgz", - "integrity": "sha512-QU7GbnQvADFXdumcdADmv4vil3bhnYl2IFHWKieRt0MgIhghgBxIB7kDKWhswcuZ0kZztVbyYjo9aCrlf62fcw==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-9.2.0.tgz", + "integrity": "sha512-wHpNJDPzM6XtZUOB3gW0J6mkFCSJilzCM3XrHI1o0C8vZmFE1snbmkIXNyoi1eV0Nxh1BMymcgz5vIMJgQtTqw==", "dev": true, "requires": { - "@angular-devkit/core": "14.0.5", - "@angular-devkit/schematics": "14.0.5", - "fs-extra": "10.1.0", - "jsonc-parser": "3.0.0", + "@angular-devkit/core": "16.0.1", + "@angular-devkit/schematics": "16.0.1", + "jsonc-parser": "3.2.0", "pluralize": "8.0.0" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.0.1.tgz", + "integrity": "sha512-2uz98IqkKJlgnHbWQ7VeL4pb+snGAZXIama2KXi+k9GsRntdcw+udX8rL3G9SdUGUF+m6+147Y1oRBMHsO/v4w==", + "dev": true, + "requires": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "rxjs": "7.8.1", + "source-map": "0.7.4" + } + }, + "@angular-devkit/schematics": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.0.1.tgz", + "integrity": "sha512-A9D0LTYmiqiBa90GKcSuWb7hUouGIbm/AHbJbjL85WLLRbQA2PwKl7P5Mpd6nS/ZC0kfG4VQY3VOaDvb3qpI9g==", + "dev": true, + "requires": { + "@angular-devkit/core": "16.0.1", + "jsonc-parser": "3.2.0", + "magic-string": "0.30.0", + "ora": "5.4.1", + "rxjs": "7.8.1" + } + }, + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "magic-string": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", + "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==", + "dev": true, + "requires": { + "@jridgewell/sourcemap-codec": "^1.4.13" + } + }, + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true + } } }, "@nestjs/testing": { @@ -16679,9 +16846,9 @@ "dev": true }, "@types/node": { - "version": "14.18.22", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.22.tgz", - "integrity": "sha512-qzaYbXVzin6EPjghf/hTdIbnVW1ErMx8rPzwRNJhlbyJhu2SyqlvjGOY/tbUt6VFyzg56lROcOeSQRInpt63Yw==", + "version": "14.18.63", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", + "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==", "dev": true }, "@types/normalize-package-data": { @@ -24302,9 +24469,9 @@ } }, "rxjs": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz", - "integrity": "sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dev": true, "requires": { "tslib": "^2.1.0" @@ -25429,9 +25596,9 @@ "dev": true }, "typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true }, "uglify-js": { diff --git a/package.json b/package.json index 1608361..1e9196f 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "@types/aws-sdk": "^2.7.0", "@types/express": "^4.17.3", "@types/jest": "25.2.3", - "@types/node": "^14.18.22", + "@types/node": "^14.18.63", "@types/superagent": "^4.1.15", "@types/supertest": "^2.0.12", "@typescript-eslint/eslint-plugin": "^5", diff --git a/src/lib/aws-service.decorator.ts b/src/lib/aws-service.decorator.ts index 2028274..319ba20 100644 --- a/src/lib/aws-service.decorator.ts +++ b/src/lib/aws-service.decorator.ts @@ -4,6 +4,6 @@ import { AwsService, AwsServiceType } from './types'; export const InjectAwsService = ( serviceConstructor: AwsServiceType, -) => { +): PropertyDecorator & ParameterDecorator => { return Inject(getAwsServiceToken(serviceConstructor)); };