From fe431b73eca03db1ce82d5cb761f8b6b920394cc Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 29 Jun 2023 13:07:47 +0200 Subject: [PATCH 01/16] add custom user agent middleware --- packages/commons/package.json | 1 + packages/commons/src/index.ts | 1 + packages/commons/src/middleware/index.ts | 1 + .../src/middleware/userAgentMiddleware.ts | 39 +++++++++++++++ packages/commons/src/version.ts | 2 + .../tests/unit/userAgentMiddleware.test.ts | 49 +++++++++++++++++++ 6 files changed, 93 insertions(+) create mode 100644 packages/commons/src/middleware/userAgentMiddleware.ts create mode 100644 packages/commons/src/version.ts create mode 100644 packages/commons/tests/unit/userAgentMiddleware.test.ts diff --git a/packages/commons/package.json b/packages/commons/package.json index 0b5af896ff..e30d4e400a 100644 --- a/packages/commons/package.json +++ b/packages/commons/package.json @@ -14,6 +14,7 @@ "test:unit": "jest --group=unit --detectOpenHandles --coverage --verbose", "test:e2e": "echo 'Not Applicable'", "watch": "jest --watch", + "generateVersionFile": "echo \"// this file is auto generated, do not modify\nmodule.exports = { version: '$(jq -r '.version' package.json)' };\" > src/version.ts", "build": "tsc", "lint": "eslint --ext .ts,.js --no-error-on-unmatched-pattern .", "lint-fix": "eslint --fix --ext .ts,.js --no-error-on-unmatched-pattern .", diff --git a/packages/commons/src/index.ts b/packages/commons/src/index.ts index 3914c0b48c..6d320e15dc 100644 --- a/packages/commons/src/index.ts +++ b/packages/commons/src/index.ts @@ -5,3 +5,4 @@ export * as ContextExamples from './samples/resources/contexts'; export * as Events from './samples/resources/events'; export * from './types/middy'; export * from './types/utils'; +export * from './middleware'; diff --git a/packages/commons/src/middleware/index.ts b/packages/commons/src/middleware/index.ts index 85f7388af3..9c32341259 100644 --- a/packages/commons/src/middleware/index.ts +++ b/packages/commons/src/middleware/index.ts @@ -1,2 +1,3 @@ export * from './cleanupMiddlewares'; export * from './constants'; +export * from './userAgentMiddleware'; diff --git a/packages/commons/src/middleware/userAgentMiddleware.ts b/packages/commons/src/middleware/userAgentMiddleware.ts new file mode 100644 index 0000000000..e507904d05 --- /dev/null +++ b/packages/commons/src/middleware/userAgentMiddleware.ts @@ -0,0 +1,39 @@ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-nocheck +/** + * @internal + */ +import { version as PT_VERSION } from '../version'; +import { userAgentMiddleware } from '@aws-sdk/middleware-user-agent'; + +const EXEC_ENV = process.env.AWS_EXECUTION_ENV || 'NA'; +const middlewareOptions = { + step: 'finalizeRequest', + name: 'addPowertoolsToUserAgent', + tags: ['POWERTOOLS', 'USER_AGENT'], +}; + +/** + * @internal + * returns a middleware function for the MiddlewareStack, that can be used for the SDK clients + * @param feature + */ +const customUserAgentMiddleware = (feature: string) => { + return (next, _context) => async (args) => { + const powertoolsUserAgent = `PT/${feature}/${PT_VERSION} PTEnv/${EXEC_ENV}`; + args.request.headers['user-agent'] = args.request.headers['user-agent'] + ? `${args.request.headers['user-agent']} ${powertoolsUserAgent}` + : `${powertoolsUserAgent}`; + + return await next(args); + }; +}; + +const addUserAgentMiddleware = (client, feature): void => { + client.middlewareStack.add( + customUserAgentMiddleware(feature), + middlewareOptions + ); +}; + +export { addUserAgentMiddleware, userAgentMiddleware }; diff --git a/packages/commons/src/version.ts b/packages/commons/src/version.ts new file mode 100644 index 0000000000..f332150d14 --- /dev/null +++ b/packages/commons/src/version.ts @@ -0,0 +1,2 @@ +// this file is auto generated, do not modify +module.exports = { version: '1.10.0' }; diff --git a/packages/commons/tests/unit/userAgentMiddleware.test.ts b/packages/commons/tests/unit/userAgentMiddleware.test.ts new file mode 100644 index 0000000000..9b47e05986 --- /dev/null +++ b/packages/commons/tests/unit/userAgentMiddleware.test.ts @@ -0,0 +1,49 @@ +import { addUserAgentMiddleware } from '../../src/middleware/userAgentMiddleware'; +import { InvokeCommand, LambdaClient } from '@aws-sdk/client-lambda'; + +describe('Function: addUserAgentMiddleware', () => { + it('adds powertools user agent to request header at the end', async () => { + const lambdaClient = new LambdaClient({ + logger: console, + region: 'us-east-1', + endpoint: 'http://localhost:9001', + maxAttempts: 1, // disable retry to have the correct number of assertions + }); + addUserAgentMiddleware(lambdaClient, 'my-feature'); + + expect(lambdaClient.middlewareStack.identify()).toContain( + 'addPowertoolsToUserAgent: POWERTOOLS,USER_AGENT' + ); + + lambdaClient.middlewareStack.add( + (next) => (args) => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + const userAgent = args?.request?.headers['user-agent']; + expect(userAgent).toContain('PT/my-feature/1.10.0 PTEnv/NA'); + // make sure it's at the end of the user agent + expect( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + userAgent + ?.split(' ') + .slice(userAgent?.split(' ').length - 2) + .join(' ') + ).toEqual('PT/my-feature/1.10.0 PTEnv/NA'); + + return next(args); + }, + { + step: 'finalizeRequest', + } + ); + try { + await lambdaClient.send( + new InvokeCommand({ + FunctionName: 'test', + Payload: new TextEncoder().encode(JSON.stringify('foo')), + }) + ); + } catch (e) {} + }); +}); From d14811aad1af796335207d13de2e47d06754df16 Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 29 Jun 2023 13:16:37 +0200 Subject: [PATCH 02/16] remove singleton for ddb client, add useragent in constructor --- .../persistence/DynamoDBPersistenceLayer.ts | 38 +++++++------------ .../DynamoDbPersistenceLayer.test.ts | 22 ++++------- 2 files changed, 21 insertions(+), 39 deletions(-) diff --git a/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts b/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts index 78d85690f7..25dc97b82d 100644 --- a/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts +++ b/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts @@ -2,21 +2,22 @@ import { IdempotencyItemAlreadyExistsError, IdempotencyItemNotFoundError, } from '../errors'; -import { IdempotencyRecordStatus } from '../types'; import type { DynamoPersistenceOptions } from '../types'; +import { IdempotencyRecordStatus } from '../types'; import { + AttributeValue, + DeleteItemCommand, DynamoDBClient, DynamoDBClientConfig, DynamoDBServiceException, - DeleteItemCommand, GetItemCommand, PutItemCommand, UpdateItemCommand, - AttributeValue, } from '@aws-sdk/client-dynamodb'; import { marshall, unmarshall } from '@aws-sdk/util-dynamodb'; import { IdempotencyRecord } from './IdempotencyRecord'; import { BasePersistenceLayer } from './BasePersistenceLayer'; +import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; /** * DynamoDB persistence layer for idempotency records. This class will use the AWS SDK V3 to write and read idempotency records from DynamoDB. @@ -28,7 +29,7 @@ import { BasePersistenceLayer } from './BasePersistenceLayer'; * @implements {BasePersistenceLayer} */ class DynamoDBPersistenceLayer extends BasePersistenceLayer { - private client?: DynamoDBClient; + private client!: DynamoDBClient; private clientConfig: DynamoDBClientConfig = {}; private dataAttr: string; private expiryAttr: string; @@ -64,18 +65,18 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { if (config?.awsSdkV3Client instanceof DynamoDBClient) { this.client = config.awsSdkV3Client; } else { - console.warn( - 'Invalid AWS SDK V3 client passed to DynamoDBPersistenceLayer. Using default client.' - ); + throw Error('Not valid DynamoDBClient provided.'); } } else { this.clientConfig = config?.clientConfig ?? {}; + this.client = new DynamoDBClient(this.clientConfig); } + + addUserAgentMiddleware(this.client, 'idempotency'); } protected async _deleteRecord(record: IdempotencyRecord): Promise { - const client = this.getClient(); - await client.send( + await this.client.send( new DeleteItemCommand({ TableName: this.tableName, Key: this.getKey(record.idempotencyKey), @@ -86,8 +87,7 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { protected async _getRecord( idempotencyKey: string ): Promise { - const client = this.getClient(); - const result = await client.send( + const result = await this.client.send( new GetItemCommand({ TableName: this.tableName, Key: this.getKey(idempotencyKey), @@ -111,8 +111,6 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { } protected async _putRecord(record: IdempotencyRecord): Promise { - const client = this.getClient(); - const item = { ...this.getKey(record.idempotencyKey), ...marshall({ @@ -163,7 +161,7 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { ].join(' OR '); const now = Date.now(); - await client.send( + await this.client.send( new PutItemCommand({ TableName: this.tableName, Item: item, @@ -195,8 +193,6 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { } protected async _updateRecord(record: IdempotencyRecord): Promise { - const client = this.getClient(); - const updateExpressionFields: string[] = [ '#response_data = :response_data', '#expiry = :expiry', @@ -219,7 +215,7 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { expressionAttributeValues[':validation_key'] = record.payloadHash; } - await client.send( + await this.client.send( new UpdateItemCommand({ TableName: this.tableName, Key: this.getKey(record.idempotencyKey), @@ -230,14 +226,6 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { ); } - private getClient(): DynamoDBClient { - if (!this.client) { - this.client = new DynamoDBClient(this.clientConfig); - } - - return this.client; - } - /** * Build primary key attribute simple or composite based on params. * diff --git a/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts b/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts index 68810e9a35..02c0dfa333 100644 --- a/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts +++ b/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts @@ -163,20 +163,14 @@ describe('Class: DynamoDBPersistenceLayer', () => { ); }); - test('when passed an invalid AWS SDK client it logs a warning', () => { - // Prepare - const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(); - - // Act - new TestDynamoDBPersistenceLayer({ - tableName: dummyTableName, - awsSdkV3Client: {} as DynamoDBClient, - }); - - // Assess - expect(consoleWarnSpy).toHaveBeenCalledWith( - 'Invalid AWS SDK V3 client passed to DynamoDBPersistenceLayer. Using default client.' - ); + test('when passed an invalid AWS SDK client, it throws an error', () => { + // Act & Assess + expect(() => { + new TestDynamoDBPersistenceLayer({ + tableName: dummyTableName, + awsSdkV3Client: {} as DynamoDBClient, + }); + }).toThrow(); }); test('when passed a client config it stores it for later use', () => { From b4bd4950747b8e2b93798229c67c9ea637123180 Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 29 Jun 2023 13:47:48 +0200 Subject: [PATCH 03/16] remove conditional, because SDK will always resolve user-agent header --- packages/commons/src/middleware/userAgentMiddleware.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/commons/src/middleware/userAgentMiddleware.ts b/packages/commons/src/middleware/userAgentMiddleware.ts index e507904d05..cd1942964d 100644 --- a/packages/commons/src/middleware/userAgentMiddleware.ts +++ b/packages/commons/src/middleware/userAgentMiddleware.ts @@ -4,7 +4,6 @@ * @internal */ import { version as PT_VERSION } from '../version'; -import { userAgentMiddleware } from '@aws-sdk/middleware-user-agent'; const EXEC_ENV = process.env.AWS_EXECUTION_ENV || 'NA'; const middlewareOptions = { @@ -21,9 +20,9 @@ const middlewareOptions = { const customUserAgentMiddleware = (feature: string) => { return (next, _context) => async (args) => { const powertoolsUserAgent = `PT/${feature}/${PT_VERSION} PTEnv/${EXEC_ENV}`; - args.request.headers['user-agent'] = args.request.headers['user-agent'] - ? `${args.request.headers['user-agent']} ${powertoolsUserAgent}` - : `${powertoolsUserAgent}`; + args.request.headers[ + 'user-agent' + ] = `${args.request.headers['user-agent']} ${powertoolsUserAgent}`; return await next(args); }; @@ -36,4 +35,4 @@ const addUserAgentMiddleware = (client, feature): void => { ); }; -export { addUserAgentMiddleware, userAgentMiddleware }; +export { addUserAgentMiddleware }; From 26cee59d8ab4284b5b2b4ba501afd67ca305024c Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 29 Jun 2023 14:08:41 +0200 Subject: [PATCH 04/16] simplify test --- .../tests/unit/userAgentMiddleware.test.ts | 60 +++++++++++-------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/packages/commons/tests/unit/userAgentMiddleware.test.ts b/packages/commons/tests/unit/userAgentMiddleware.test.ts index 9b47e05986..03479e29a5 100644 --- a/packages/commons/tests/unit/userAgentMiddleware.test.ts +++ b/packages/commons/tests/unit/userAgentMiddleware.test.ts @@ -1,6 +1,19 @@ import { addUserAgentMiddleware } from '../../src/middleware/userAgentMiddleware'; import { InvokeCommand, LambdaClient } from '@aws-sdk/client-lambda'; +/** + * Logs request headers + * + * This is a middleware we use to test + */ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +const logHeadersMiddleware = (next, _context) => async (args) => { + console.log(args.request.headers); + + return await next(args); +}; + describe('Function: addUserAgentMiddleware', () => { it('adds powertools user agent to request header at the end', async () => { const lambdaClient = new LambdaClient({ @@ -9,41 +22,36 @@ describe('Function: addUserAgentMiddleware', () => { endpoint: 'http://localhost:9001', maxAttempts: 1, // disable retry to have the correct number of assertions }); + + // Set a spy on the console.log method, so we can check the headers + const consoleSpy = jest.spyOn(console, 'log').mockImplementation(); + addUserAgentMiddleware(lambdaClient, 'my-feature'); expect(lambdaClient.middlewareStack.identify()).toContain( 'addPowertoolsToUserAgent: POWERTOOLS,USER_AGENT' ); - lambdaClient.middlewareStack.add( - (next) => (args) => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - const userAgent = args?.request?.headers['user-agent']; - expect(userAgent).toContain('PT/my-feature/1.10.0 PTEnv/NA'); - // make sure it's at the end of the user agent - expect( - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - userAgent - ?.split(' ') - .slice(userAgent?.split(' ').length - 2) - .join(' ') - ).toEqual('PT/my-feature/1.10.0 PTEnv/NA'); - - return next(args); - }, - { - step: 'finalizeRequest', - } - ); - try { - await lambdaClient.send( + lambdaClient.middlewareStack.addRelativeTo(logHeadersMiddleware, { + relation: 'after', + toMiddleware: 'addPowertoolsToUserAgent', + name: 'logHeadersMiddleware', + tags: ['TEST'], + }); + + await expect(() => + lambdaClient.send( new InvokeCommand({ FunctionName: 'test', Payload: new TextEncoder().encode(JSON.stringify('foo')), }) - ); - } catch (e) {} + ) + ).rejects.toThrow(); + + expect(consoleSpy).toHaveBeenCalledWith( + expect.objectContaining({ + 'user-agent': expect.stringContaining('PT/my-feature/1.10.0 PTEnv/NA'), + }) + ); }); }); From 8296eeaeaa288c53a06ed34313d65b5e9badf68d Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 29 Jun 2023 14:09:07 +0200 Subject: [PATCH 05/16] remove retry, no longer needed --- packages/commons/tests/unit/userAgentMiddleware.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/commons/tests/unit/userAgentMiddleware.test.ts b/packages/commons/tests/unit/userAgentMiddleware.test.ts index 03479e29a5..6fc8f8ddea 100644 --- a/packages/commons/tests/unit/userAgentMiddleware.test.ts +++ b/packages/commons/tests/unit/userAgentMiddleware.test.ts @@ -20,7 +20,6 @@ describe('Function: addUserAgentMiddleware', () => { logger: console, region: 'us-east-1', endpoint: 'http://localhost:9001', - maxAttempts: 1, // disable retry to have the correct number of assertions }); // Set a spy on the console.log method, so we can check the headers From bdda1436d9c433be1c9a126e9aebe0fb36a2a213 Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 29 Jun 2023 14:14:19 +0200 Subject: [PATCH 06/16] remove ua from idempotency, will be done in separate PR --- .../idempotency/src/persistence/DynamoDBPersistenceLayer.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts b/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts index 25dc97b82d..ea5a58b7ed 100644 --- a/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts +++ b/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts @@ -17,7 +17,6 @@ import { import { marshall, unmarshall } from '@aws-sdk/util-dynamodb'; import { IdempotencyRecord } from './IdempotencyRecord'; import { BasePersistenceLayer } from './BasePersistenceLayer'; -import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; /** * DynamoDB persistence layer for idempotency records. This class will use the AWS SDK V3 to write and read idempotency records from DynamoDB. @@ -71,8 +70,6 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { this.clientConfig = config?.clientConfig ?? {}; this.client = new DynamoDBClient(this.clientConfig); } - - addUserAgentMiddleware(this.client, 'idempotency'); } protected async _deleteRecord(record: IdempotencyRecord): Promise { From 1ad12b4388459b4dc427dac7ddd066137452b3c1 Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 29 Jun 2023 17:02:36 +0200 Subject: [PATCH 07/16] review changes --- packages/commons/package.json | 2 +- packages/commons/src/index.ts | 2 +- packages/commons/src/middleware/index.ts | 1 - packages/commons/src/{middleware => }/userAgentMiddleware.ts | 2 +- packages/commons/src/version.ts | 2 +- packages/commons/tests/unit/userAgentMiddleware.test.ts | 3 +-- 6 files changed, 5 insertions(+), 7 deletions(-) rename packages/commons/src/{middleware => }/userAgentMiddleware.ts (94%) diff --git a/packages/commons/package.json b/packages/commons/package.json index e30d4e400a..963116af19 100644 --- a/packages/commons/package.json +++ b/packages/commons/package.json @@ -14,7 +14,7 @@ "test:unit": "jest --group=unit --detectOpenHandles --coverage --verbose", "test:e2e": "echo 'Not Applicable'", "watch": "jest --watch", - "generateVersionFile": "echo \"// this file is auto generated, do not modify\nmodule.exports = { version: '$(jq -r '.version' package.json)' };\" > src/version.ts", + "generateVersionFile": "echo \"// this file is auto generated, do not modify\nexport const PT_VERSION = '$(jq -r '.version' package.json)';\" > src/version.ts", "build": "tsc", "lint": "eslint --ext .ts,.js --no-error-on-unmatched-pattern .", "lint-fix": "eslint --fix --ext .ts,.js --no-error-on-unmatched-pattern .", diff --git a/packages/commons/src/index.ts b/packages/commons/src/index.ts index 6d320e15dc..2192dc8bb8 100644 --- a/packages/commons/src/index.ts +++ b/packages/commons/src/index.ts @@ -5,4 +5,4 @@ export * as ContextExamples from './samples/resources/contexts'; export * as Events from './samples/resources/events'; export * from './types/middy'; export * from './types/utils'; -export * from './middleware'; +export * from './userAgentMiddleware'; diff --git a/packages/commons/src/middleware/index.ts b/packages/commons/src/middleware/index.ts index 9c32341259..85f7388af3 100644 --- a/packages/commons/src/middleware/index.ts +++ b/packages/commons/src/middleware/index.ts @@ -1,3 +1,2 @@ export * from './cleanupMiddlewares'; export * from './constants'; -export * from './userAgentMiddleware'; diff --git a/packages/commons/src/middleware/userAgentMiddleware.ts b/packages/commons/src/userAgentMiddleware.ts similarity index 94% rename from packages/commons/src/middleware/userAgentMiddleware.ts rename to packages/commons/src/userAgentMiddleware.ts index cd1942964d..4a019366e9 100644 --- a/packages/commons/src/middleware/userAgentMiddleware.ts +++ b/packages/commons/src/userAgentMiddleware.ts @@ -3,7 +3,7 @@ /** * @internal */ -import { version as PT_VERSION } from '../version'; +import { PT_VERSION } from './version'; const EXEC_ENV = process.env.AWS_EXECUTION_ENV || 'NA'; const middlewareOptions = { diff --git a/packages/commons/src/version.ts b/packages/commons/src/version.ts index f332150d14..aed11641f3 100644 --- a/packages/commons/src/version.ts +++ b/packages/commons/src/version.ts @@ -1,2 +1,2 @@ // this file is auto generated, do not modify -module.exports = { version: '1.10.0' }; +export const PT_VERSION = '1.10.0'; diff --git a/packages/commons/tests/unit/userAgentMiddleware.test.ts b/packages/commons/tests/unit/userAgentMiddleware.test.ts index 6fc8f8ddea..167d868a1f 100644 --- a/packages/commons/tests/unit/userAgentMiddleware.test.ts +++ b/packages/commons/tests/unit/userAgentMiddleware.test.ts @@ -1,4 +1,4 @@ -import { addUserAgentMiddleware } from '../../src/middleware/userAgentMiddleware'; +import { addUserAgentMiddleware } from '../../src/userAgentMiddleware'; import { InvokeCommand, LambdaClient } from '@aws-sdk/client-lambda'; /** @@ -17,7 +17,6 @@ const logHeadersMiddleware = (next, _context) => async (args) => { describe('Function: addUserAgentMiddleware', () => { it('adds powertools user agent to request header at the end', async () => { const lambdaClient = new LambdaClient({ - logger: console, region: 'us-east-1', endpoint: 'http://localhost:9001', }); From 2a23d254d432afde4e6d2618cd7bfeb37590ad42 Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 29 Jun 2023 17:04:53 +0200 Subject: [PATCH 08/16] revert client lazy loading --- .../persistence/DynamoDBPersistenceLayer.ts | 35 +++++++++++++------ .../DynamoDbPersistenceLayer.test.ts | 22 +++++++----- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts b/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts index ea5a58b7ed..78d85690f7 100644 --- a/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts +++ b/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts @@ -2,17 +2,17 @@ import { IdempotencyItemAlreadyExistsError, IdempotencyItemNotFoundError, } from '../errors'; -import type { DynamoPersistenceOptions } from '../types'; import { IdempotencyRecordStatus } from '../types'; +import type { DynamoPersistenceOptions } from '../types'; import { - AttributeValue, - DeleteItemCommand, DynamoDBClient, DynamoDBClientConfig, DynamoDBServiceException, + DeleteItemCommand, GetItemCommand, PutItemCommand, UpdateItemCommand, + AttributeValue, } from '@aws-sdk/client-dynamodb'; import { marshall, unmarshall } from '@aws-sdk/util-dynamodb'; import { IdempotencyRecord } from './IdempotencyRecord'; @@ -28,7 +28,7 @@ import { BasePersistenceLayer } from './BasePersistenceLayer'; * @implements {BasePersistenceLayer} */ class DynamoDBPersistenceLayer extends BasePersistenceLayer { - private client!: DynamoDBClient; + private client?: DynamoDBClient; private clientConfig: DynamoDBClientConfig = {}; private dataAttr: string; private expiryAttr: string; @@ -64,16 +64,18 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { if (config?.awsSdkV3Client instanceof DynamoDBClient) { this.client = config.awsSdkV3Client; } else { - throw Error('Not valid DynamoDBClient provided.'); + console.warn( + 'Invalid AWS SDK V3 client passed to DynamoDBPersistenceLayer. Using default client.' + ); } } else { this.clientConfig = config?.clientConfig ?? {}; - this.client = new DynamoDBClient(this.clientConfig); } } protected async _deleteRecord(record: IdempotencyRecord): Promise { - await this.client.send( + const client = this.getClient(); + await client.send( new DeleteItemCommand({ TableName: this.tableName, Key: this.getKey(record.idempotencyKey), @@ -84,7 +86,8 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { protected async _getRecord( idempotencyKey: string ): Promise { - const result = await this.client.send( + const client = this.getClient(); + const result = await client.send( new GetItemCommand({ TableName: this.tableName, Key: this.getKey(idempotencyKey), @@ -108,6 +111,8 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { } protected async _putRecord(record: IdempotencyRecord): Promise { + const client = this.getClient(); + const item = { ...this.getKey(record.idempotencyKey), ...marshall({ @@ -158,7 +163,7 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { ].join(' OR '); const now = Date.now(); - await this.client.send( + await client.send( new PutItemCommand({ TableName: this.tableName, Item: item, @@ -190,6 +195,8 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { } protected async _updateRecord(record: IdempotencyRecord): Promise { + const client = this.getClient(); + const updateExpressionFields: string[] = [ '#response_data = :response_data', '#expiry = :expiry', @@ -212,7 +219,7 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { expressionAttributeValues[':validation_key'] = record.payloadHash; } - await this.client.send( + await client.send( new UpdateItemCommand({ TableName: this.tableName, Key: this.getKey(record.idempotencyKey), @@ -223,6 +230,14 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { ); } + private getClient(): DynamoDBClient { + if (!this.client) { + this.client = new DynamoDBClient(this.clientConfig); + } + + return this.client; + } + /** * Build primary key attribute simple or composite based on params. * diff --git a/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts b/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts index 02c0dfa333..68810e9a35 100644 --- a/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts +++ b/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts @@ -163,14 +163,20 @@ describe('Class: DynamoDBPersistenceLayer', () => { ); }); - test('when passed an invalid AWS SDK client, it throws an error', () => { - // Act & Assess - expect(() => { - new TestDynamoDBPersistenceLayer({ - tableName: dummyTableName, - awsSdkV3Client: {} as DynamoDBClient, - }); - }).toThrow(); + test('when passed an invalid AWS SDK client it logs a warning', () => { + // Prepare + const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(); + + // Act + new TestDynamoDBPersistenceLayer({ + tableName: dummyTableName, + awsSdkV3Client: {} as DynamoDBClient, + }); + + // Assess + expect(consoleWarnSpy).toHaveBeenCalledWith( + 'Invalid AWS SDK V3 client passed to DynamoDBPersistenceLayer. Using default client.' + ); }); test('when passed a client config it stores it for later use', () => { From 54bd3eddc39dc09885bb946daf8cbf376f1ce8a9 Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 29 Jun 2023 17:18:21 +0200 Subject: [PATCH 09/16] Revert "remove ua from idempotency, will be done in separate PR" This reverts commit bdda1436d9c433be1c9a126e9aebe0fb36a2a213. --- .../idempotency/src/persistence/DynamoDBPersistenceLayer.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts b/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts index 78d85690f7..a37fdd0352 100644 --- a/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts +++ b/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts @@ -17,6 +17,7 @@ import { import { marshall, unmarshall } from '@aws-sdk/util-dynamodb'; import { IdempotencyRecord } from './IdempotencyRecord'; import { BasePersistenceLayer } from './BasePersistenceLayer'; +import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; /** * DynamoDB persistence layer for idempotency records. This class will use the AWS SDK V3 to write and read idempotency records from DynamoDB. @@ -71,6 +72,8 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { } else { this.clientConfig = config?.clientConfig ?? {}; } + + addUserAgentMiddleware(this.client, 'idempotency'); } protected async _deleteRecord(record: IdempotencyRecord): Promise { From 7a73b3b8235575a028b388588cde03d7a90cf86f Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 29 Jun 2023 17:23:12 +0200 Subject: [PATCH 10/16] revert the revert, misunderstanding --- .../persistence/DynamoDBPersistenceLayer.ts | 35 ++++++------------- .../DynamoDbPersistenceLayer.test.ts | 22 +++++------- 2 files changed, 18 insertions(+), 39 deletions(-) diff --git a/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts b/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts index a37fdd0352..78cb1fbffc 100644 --- a/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts +++ b/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts @@ -2,17 +2,17 @@ import { IdempotencyItemAlreadyExistsError, IdempotencyItemNotFoundError, } from '../errors'; -import { IdempotencyRecordStatus } from '../types'; import type { DynamoPersistenceOptions } from '../types'; +import { IdempotencyRecordStatus } from '../types'; import { + AttributeValue, + DeleteItemCommand, DynamoDBClient, DynamoDBClientConfig, DynamoDBServiceException, - DeleteItemCommand, GetItemCommand, PutItemCommand, UpdateItemCommand, - AttributeValue, } from '@aws-sdk/client-dynamodb'; import { marshall, unmarshall } from '@aws-sdk/util-dynamodb'; import { IdempotencyRecord } from './IdempotencyRecord'; @@ -29,7 +29,7 @@ import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; * @implements {BasePersistenceLayer} */ class DynamoDBPersistenceLayer extends BasePersistenceLayer { - private client?: DynamoDBClient; + private client: DynamoDBClient; private clientConfig: DynamoDBClientConfig = {}; private dataAttr: string; private expiryAttr: string; @@ -65,20 +65,18 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { if (config?.awsSdkV3Client instanceof DynamoDBClient) { this.client = config.awsSdkV3Client; } else { - console.warn( - 'Invalid AWS SDK V3 client passed to DynamoDBPersistenceLayer. Using default client.' - ); + throw Error('Not valid DynamoDBClient provided.'); } } else { this.clientConfig = config?.clientConfig ?? {}; + this.client = new DynamoDBClient(this.clientConfig); } addUserAgentMiddleware(this.client, 'idempotency'); } protected async _deleteRecord(record: IdempotencyRecord): Promise { - const client = this.getClient(); - await client.send( + await this.client.send( new DeleteItemCommand({ TableName: this.tableName, Key: this.getKey(record.idempotencyKey), @@ -89,8 +87,7 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { protected async _getRecord( idempotencyKey: string ): Promise { - const client = this.getClient(); - const result = await client.send( + const result = await this.client.send( new GetItemCommand({ TableName: this.tableName, Key: this.getKey(idempotencyKey), @@ -114,8 +111,6 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { } protected async _putRecord(record: IdempotencyRecord): Promise { - const client = this.getClient(); - const item = { ...this.getKey(record.idempotencyKey), ...marshall({ @@ -166,7 +161,7 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { ].join(' OR '); const now = Date.now(); - await client.send( + await this.client.send( new PutItemCommand({ TableName: this.tableName, Item: item, @@ -198,8 +193,6 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { } protected async _updateRecord(record: IdempotencyRecord): Promise { - const client = this.getClient(); - const updateExpressionFields: string[] = [ '#response_data = :response_data', '#expiry = :expiry', @@ -222,7 +215,7 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { expressionAttributeValues[':validation_key'] = record.payloadHash; } - await client.send( + await this.client.send( new UpdateItemCommand({ TableName: this.tableName, Key: this.getKey(record.idempotencyKey), @@ -233,14 +226,6 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { ); } - private getClient(): DynamoDBClient { - if (!this.client) { - this.client = new DynamoDBClient(this.clientConfig); - } - - return this.client; - } - /** * Build primary key attribute simple or composite based on params. * diff --git a/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts b/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts index 68810e9a35..02c0dfa333 100644 --- a/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts +++ b/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts @@ -163,20 +163,14 @@ describe('Class: DynamoDBPersistenceLayer', () => { ); }); - test('when passed an invalid AWS SDK client it logs a warning', () => { - // Prepare - const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(); - - // Act - new TestDynamoDBPersistenceLayer({ - tableName: dummyTableName, - awsSdkV3Client: {} as DynamoDBClient, - }); - - // Assess - expect(consoleWarnSpy).toHaveBeenCalledWith( - 'Invalid AWS SDK V3 client passed to DynamoDBPersistenceLayer. Using default client.' - ); + test('when passed an invalid AWS SDK client, it throws an error', () => { + // Act & Assess + expect(() => { + new TestDynamoDBPersistenceLayer({ + tableName: dummyTableName, + awsSdkV3Client: {} as DynamoDBClient, + }); + }).toThrow(); }); test('when passed a client config it stores it for later use', () => { From 4a7d814041788a3eda822ba8e86c7bb0ccccd4ac Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Thu, 29 Jun 2023 17:24:33 +0200 Subject: [PATCH 11/16] add explicit ts-ignore instead of the entire file --- packages/commons/src/userAgentMiddleware.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/commons/src/userAgentMiddleware.ts b/packages/commons/src/userAgentMiddleware.ts index 4a019366e9..4bf45bfc8e 100644 --- a/packages/commons/src/userAgentMiddleware.ts +++ b/packages/commons/src/userAgentMiddleware.ts @@ -1,5 +1,3 @@ -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-nocheck /** * @internal */ @@ -18,6 +16,8 @@ const middlewareOptions = { * @param feature */ const customUserAgentMiddleware = (feature: string) => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore return (next, _context) => async (args) => { const powertoolsUserAgent = `PT/${feature}/${PT_VERSION} PTEnv/${EXEC_ENV}`; args.request.headers[ @@ -28,7 +28,9 @@ const customUserAgentMiddleware = (feature: string) => { }; }; -const addUserAgentMiddleware = (client, feature): void => { +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +const addUserAgentMiddleware = (client, feature: string): void => { client.middlewareStack.add( customUserAgentMiddleware(feature), middlewareOptions From 8d3c8395ba4fbf72f1fb2de17c10a0f3cf22a4f8 Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Sat, 1 Jul 2023 13:57:32 +0200 Subject: [PATCH 12/16] parameterized tests for useragent --- package-lock.json | 4 + packages/commons/package.json | 4 + packages/commons/src/userAgentMiddleware.ts | 7 +- .../tests/unit/userAgentMiddleware.test.ts | 115 +++++++++++------- 4 files changed, 82 insertions(+), 48 deletions(-) diff --git a/package-lock.json b/package-lock.json index f259fcb6a3..a859fa3a8a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18006,7 +18006,11 @@ "version": "1.11.0", "license": "MIT-0", "devDependencies": { + "@aws-sdk/client-appconfigdata": "^3.360.0", + "@aws-sdk/client-dynamodb": "^3.360.0", "@aws-sdk/client-lambda": "^3.360.0", + "@aws-sdk/client-secrets-manager": "^3.360.0", + "@aws-sdk/client-ssm": "^3.360.0", "@aws-sdk/util-utf8-node": "^3.259.0" } }, diff --git a/packages/commons/package.json b/packages/commons/package.json index 5eb3bc13f3..1d058b12e3 100644 --- a/packages/commons/package.json +++ b/packages/commons/package.json @@ -48,6 +48,10 @@ ], "devDependencies": { "@aws-sdk/client-lambda": "^3.360.0", + "@aws-sdk/client-dynamodb": "^3.360.0", + "@aws-sdk/client-appconfigdata": "^3.360.0", + "@aws-sdk/client-secrets-manager": "^3.360.0", + "@aws-sdk/client-ssm": "^3.360.0", "@aws-sdk/util-utf8-node": "^3.259.0" } } diff --git a/packages/commons/src/userAgentMiddleware.ts b/packages/commons/src/userAgentMiddleware.ts index 4bf45bfc8e..0728259345 100644 --- a/packages/commons/src/userAgentMiddleware.ts +++ b/packages/commons/src/userAgentMiddleware.ts @@ -1,11 +1,12 @@ /** * @internal */ -import { PT_VERSION } from './version'; +import { version as PT_VERSION } from '../package.json'; const EXEC_ENV = process.env.AWS_EXECUTION_ENV || 'NA'; const middlewareOptions = { - step: 'finalizeRequest', + relation: 'after', + toMiddleware: 'getUserAgentMiddleware', name: 'addPowertoolsToUserAgent', tags: ['POWERTOOLS', 'USER_AGENT'], }; @@ -31,7 +32,7 @@ const customUserAgentMiddleware = (feature: string) => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore const addUserAgentMiddleware = (client, feature: string): void => { - client.middlewareStack.add( + client.middlewareStack.addRelativeTo( customUserAgentMiddleware(feature), middlewareOptions ); diff --git a/packages/commons/tests/unit/userAgentMiddleware.test.ts b/packages/commons/tests/unit/userAgentMiddleware.test.ts index 167d868a1f..477860236e 100644 --- a/packages/commons/tests/unit/userAgentMiddleware.test.ts +++ b/packages/commons/tests/unit/userAgentMiddleware.test.ts @@ -1,55 +1,80 @@ import { addUserAgentMiddleware } from '../../src/userAgentMiddleware'; import { InvokeCommand, LambdaClient } from '@aws-sdk/client-lambda'; +import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; +import { ScanCommand } from '@aws-sdk/lib-dynamodb'; +import { GetParameterCommand, SSMClient } from '@aws-sdk/client-ssm'; -/** - * Logs request headers - * - * This is a middleware we use to test - */ -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore -const logHeadersMiddleware = (next, _context) => async (args) => { - console.log(args.request.headers); - - return await next(args); +const options = { + region: 'us-east-1', + endpoint: 'http://localhost:9001', + credentials: { + accessKeyId: 'test', + secretAccessKey: 'test', + sessionToken: 'test', + }, }; -describe('Function: addUserAgentMiddleware', () => { - it('adds powertools user agent to request header at the end', async () => { - const lambdaClient = new LambdaClient({ - region: 'us-east-1', - endpoint: 'http://localhost:9001', - }); - - // Set a spy on the console.log method, so we can check the headers - const consoleSpy = jest.spyOn(console, 'log').mockImplementation(); - - addUserAgentMiddleware(lambdaClient, 'my-feature'); +describe('Given a client of instance: ', () => { + it.each([ + { + name: 'LambdaClient', + client: new LambdaClient(options), + command: new InvokeCommand({ FunctionName: 'test', Payload: '' }), + }, + { + name: 'DynamoDBClient', + client: new DynamoDBClient(options), + command: new ScanCommand({ TableName: 'test' }), + }, + { + name: 'SSMClient', + client: new SSMClient(options), + command: new GetParameterCommand({ Name: 'test' }), + }, + ])( + `using $name, add powertools user agent to request header at the end`, + async ({ client, command }) => { + addUserAgentMiddleware(client, 'my-feature'); - expect(lambdaClient.middlewareStack.identify()).toContain( - 'addPowertoolsToUserAgent: POWERTOOLS,USER_AGENT' - ); + expect(client.middlewareStack.identify()).toContain( + 'addPowertoolsToUserAgent: POWERTOOLS,USER_AGENT' + ); - lambdaClient.middlewareStack.addRelativeTo(logHeadersMiddleware, { - relation: 'after', - toMiddleware: 'addPowertoolsToUserAgent', - name: 'logHeadersMiddleware', - tags: ['TEST'], - }); + client.middlewareStack.addRelativeTo( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + (next) => (args) => { + const userAgent = args?.request?.headers['user-agent']; + expect(userAgent).toContain('PT/my-feature/1.11.0 PTEnv/NA'); + // make sure it's at the end of the user agent + expect( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + userAgent + ?.split(' ') + .slice(userAgent?.split(' ').length - 2) // take the last to entries of the user-agent header + .join(' ') + ).toEqual('PT/my-feature/1.11.0 PTEnv/NA'); - await expect(() => - lambdaClient.send( - new InvokeCommand({ - FunctionName: 'test', - Payload: new TextEncoder().encode(JSON.stringify('foo')), - }) - ) - ).rejects.toThrow(); + return next(args); + }, + { + relation: 'after', + toMiddleware: 'addPowertoolsToUserAgent', + name: 'testUserAgentHeader', + tags: ['TEST'], + } + ); - expect(consoleSpy).toHaveBeenCalledWith( - expect.objectContaining({ - 'user-agent': expect.stringContaining('PT/my-feature/1.10.0 PTEnv/NA'), - }) - ); - }); + try { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + await client.send(command); + } catch (e) { + if (e instanceof Error && e.name === 'JestAssertionError') { + throw e; + } + } + } + ); }); From 30f3cf682185e6849bad5da53461c975eab25f13 Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Sat, 1 Jul 2023 13:58:57 +0200 Subject: [PATCH 13/16] in case of failure, warn and don't block user code --- packages/commons/src/userAgentMiddleware.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/commons/src/userAgentMiddleware.ts b/packages/commons/src/userAgentMiddleware.ts index 0728259345..98324b19f9 100644 --- a/packages/commons/src/userAgentMiddleware.ts +++ b/packages/commons/src/userAgentMiddleware.ts @@ -32,10 +32,14 @@ const customUserAgentMiddleware = (feature: string) => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore const addUserAgentMiddleware = (client, feature: string): void => { - client.middlewareStack.addRelativeTo( - customUserAgentMiddleware(feature), - middlewareOptions - ); + try { + client.middlewareStack.addRelativeTo( + customUserAgentMiddleware(feature), + middlewareOptions + ); + } catch (e) { + console.warn('Failed to add user agent middleware', e); + } }; export { addUserAgentMiddleware }; From 4cbc5267808362e0139c0081afaf18b922ae919e Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Mon, 3 Jul 2023 09:04:01 +0200 Subject: [PATCH 14/16] add test to check if middleware absorbs an error and continue --- .../commons/tests/unit/userAgentMiddleware.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/commons/tests/unit/userAgentMiddleware.test.ts b/packages/commons/tests/unit/userAgentMiddleware.test.ts index 477860236e..b60e6c1051 100644 --- a/packages/commons/tests/unit/userAgentMiddleware.test.ts +++ b/packages/commons/tests/unit/userAgentMiddleware.test.ts @@ -77,4 +77,17 @@ describe('Given a client of instance: ', () => { } } ); + + it('should not throw erro, when client fails to add middleware', () => { + // create mock client that throws error when adding middleware + const client = { + middlewareStack: { + addRelativeTo: () => { + throw new Error('test'); + }, + }, + }; + + expect(() => addUserAgentMiddleware(client, 'my-feature')).not.toThrow(); + }); }); From 89cb7f71c44d7b1c1c90d697c2977e1934c9f778 Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Mon, 3 Jul 2023 09:07:25 +0200 Subject: [PATCH 15/16] add more client to useragent test --- .../tests/unit/userAgentMiddleware.test.ts | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/commons/tests/unit/userAgentMiddleware.test.ts b/packages/commons/tests/unit/userAgentMiddleware.test.ts index b60e6c1051..da71ecd8a5 100644 --- a/packages/commons/tests/unit/userAgentMiddleware.test.ts +++ b/packages/commons/tests/unit/userAgentMiddleware.test.ts @@ -3,6 +3,12 @@ import { InvokeCommand, LambdaClient } from '@aws-sdk/client-lambda'; import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; import { ScanCommand } from '@aws-sdk/lib-dynamodb'; import { GetParameterCommand, SSMClient } from '@aws-sdk/client-ssm'; +import { version as PT_VERSION } from '../../package.json'; +import { AppConfigDataClient } from '@aws-sdk/client-appconfigdata'; +import { + GetSecretValueCommand, + SecretsManagerClient, +} from '@aws-sdk/client-secrets-manager'; const options = { region: 'us-east-1', @@ -31,6 +37,16 @@ describe('Given a client of instance: ', () => { client: new SSMClient(options), command: new GetParameterCommand({ Name: 'test' }), }, + { + name: 'AppConfigDataClient', + client: new AppConfigDataClient(options), + command: new GetParameterCommand({ Name: 'test' }), + }, + { + name: 'SecretsManagerClient', + client: new SecretsManagerClient(options), + command: new GetSecretValueCommand({ SecretId: 'test' }), + }, ])( `using $name, add powertools user agent to request header at the end`, async ({ client, command }) => { @@ -45,7 +61,7 @@ describe('Given a client of instance: ', () => { // @ts-ignore (next) => (args) => { const userAgent = args?.request?.headers['user-agent']; - expect(userAgent).toContain('PT/my-feature/1.11.0 PTEnv/NA'); + expect(userAgent).toContain(`PT/my-feature/${PT_VERSION} PTEnv/NA`); // make sure it's at the end of the user agent expect( // eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -54,7 +70,7 @@ describe('Given a client of instance: ', () => { ?.split(' ') .slice(userAgent?.split(' ').length - 2) // take the last to entries of the user-agent header .join(' ') - ).toEqual('PT/my-feature/1.11.0 PTEnv/NA'); + ).toEqual(`PT/my-feature/${PT_VERSION} PTEnv/NA`); return next(args); }, From 0af820c7652e5a5d5afb2fc31b8cb94f00ce877b Mon Sep 17 00:00:00 2001 From: Alexander Melnyk Date: Mon, 3 Jul 2023 12:07:54 +0200 Subject: [PATCH 16/16] fix imports --- packages/commons/src/userAgentMiddleware.ts | 4 ++-- packages/commons/src/version.ts | 2 +- packages/idempotency/src/middleware/makeHandlerIdempotent.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/commons/src/userAgentMiddleware.ts b/packages/commons/src/userAgentMiddleware.ts index 98324b19f9..2f66661ef8 100644 --- a/packages/commons/src/userAgentMiddleware.ts +++ b/packages/commons/src/userAgentMiddleware.ts @@ -1,8 +1,8 @@ +import { PT_VERSION } from './version'; + /** * @internal */ -import { version as PT_VERSION } from '../package.json'; - const EXEC_ENV = process.env.AWS_EXECUTION_ENV || 'NA'; const middlewareOptions = { relation: 'after', diff --git a/packages/commons/src/version.ts b/packages/commons/src/version.ts index aed11641f3..aab8359875 100644 --- a/packages/commons/src/version.ts +++ b/packages/commons/src/version.ts @@ -1,2 +1,2 @@ // this file is auto generated, do not modify -export const PT_VERSION = '1.10.0'; +export const PT_VERSION = '1.11.0'; diff --git a/packages/idempotency/src/middleware/makeHandlerIdempotent.ts b/packages/idempotency/src/middleware/makeHandlerIdempotent.ts index b0f574cb20..784b438d62 100644 --- a/packages/idempotency/src/middleware/makeHandlerIdempotent.ts +++ b/packages/idempotency/src/middleware/makeHandlerIdempotent.ts @@ -8,11 +8,11 @@ import { } from '../errors'; import { IdempotencyRecord } from '../persistence'; import { MAX_RETRIES } from '../constants'; -import type { +import type { IdempotencyLambdaHandlerOptions } from '../types'; +import { MiddlewareLikeObj, MiddyLikeRequest, } from '@aws-lambda-powertools/commons'; -import type { IdempotencyLambdaHandlerOptions } from '../types'; /** * A middy middleware to make your Lambda Handler idempotent.