From 25d8c4883d1539c7cd1c6d5bf03491785da0d9ff Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Fri, 11 Nov 2022 19:27:24 +0100 Subject: [PATCH 01/11] chore: fix package.lock & package --- package-lock.json | 964 ++++++++++++++++++++++++------ package.json | 5 +- packages/idempotency/package.json | 16 +- 3 files changed, 801 insertions(+), 184 deletions(-) diff --git a/package-lock.json b/package-lock.json index e743677bb0..a8254cf368 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,8 @@ "packages/commons", "packages/logger", "packages/metrics", - "packages/tracer" + "packages/tracer", + "packages/idempotency" ], "dependencies": { "hosted-git-info": "^5.0.0" @@ -217,7 +218,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-2.0.0.tgz", "integrity": "sha512-pkVXf/dq6PITJ0jzYZ69VhL8VFOFoPZLZqtU/12SGnzYuJOOGNfF41q9GxdI1yqC8R13Rq3jOLKDFpUJFT5eTA==", - "dev": true, "dependencies": { "tslib": "^1.11.1" } @@ -225,14 +225,12 @@ "node_modules/@aws-crypto/ie11-detection/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@aws-crypto/sha256-browser": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-2.0.0.tgz", "integrity": "sha512-rYXOQ8BFOaqMEHJrLHul/25ckWH6GTJtdLSajhlqGMx0PmSueAuvboCuZCTqEKlxR8CQOwRarxYMZZSYlhRA1A==", - "dev": true, "dependencies": { "@aws-crypto/ie11-detection": "^2.0.0", "@aws-crypto/sha256-js": "^2.0.0", @@ -247,14 +245,12 @@ "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@aws-crypto/sha256-js": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-2.0.0.tgz", "integrity": "sha512-VZY+mCY4Nmrs5WGfitmNqXzaE873fcIZDu54cbaDaaamsaTOP1DBImV9F4pICc3EHjQXujyE8jig+PFCaew9ig==", - "dev": true, "dependencies": { "@aws-crypto/util": "^2.0.0", "@aws-sdk/types": "^3.1.0", @@ -264,14 +260,12 @@ "node_modules/@aws-crypto/sha256-js/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@aws-crypto/supports-web-crypto": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-2.0.0.tgz", "integrity": "sha512-Ge7WQ3E0OC7FHYprsZV3h0QIcpdyJLvIeg+uTuHqRYm8D6qCFJoiC+edSzSyFiHtZf+NOQDJ1q46qxjtzIY2nA==", - "dev": true, "dependencies": { "tslib": "^1.11.1" } @@ -279,14 +273,12 @@ "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@aws-crypto/util": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-2.0.1.tgz", "integrity": "sha512-JJmFFwvbm08lULw4Nm5QOLg8+lAQeC8aCXK5xrtxntYzYXCGfHwUJ4Is3770Q7HmICsXthGQ+ZsDL7C2uH3yBQ==", - "dev": true, "dependencies": { "@aws-sdk/types": "^3.1.0", "@aws-sdk/util-utf8-browser": "^3.0.0", @@ -296,13 +288,16 @@ "node_modules/@aws-crypto/util/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@aws-lambda-powertools/commons": { "resolved": "packages/commons", "link": true }, + "node_modules/@aws-lambda-powertools/idempotency": { + "resolved": "packages/idempotency", + "link": true + }, "node_modules/@aws-lambda-powertools/logger": { "resolved": "packages/logger", "link": true @@ -319,7 +314,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.110.0.tgz", "integrity": "sha512-zok/WEVuK7Jh6V9YeA56pNZtxUASon9LTkS7vE65A4UFmNkPGNBCNgoiBcbhWfxwrZ8wtXcQk6rtUut39831mA==", - "dev": true, "dependencies": { "@aws-sdk/types": "3.110.0", "tslib": "^2.3.1" @@ -332,7 +326,6 @@ "version": "3.113.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.113.0.tgz", "integrity": "sha512-tp0/smnSBqoPdSbZqRaH46S9cDkOMXsbG8Qph+gV3+SL+V3nJLeGFzA+3WPmF0l0Bnv0/9Tms4ySZB0MsBSy/A==", - "dev": true, "dependencies": { "@aws-crypto/sha256-browser": "2.0.0", "@aws-crypto/sha256-js": "2.0.0", @@ -380,7 +373,6 @@ "version": "3.112.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.112.0.tgz", "integrity": "sha512-FwFmiapxuVQiyMdDaBvCpajnJkVWEUHBdO+7rIpzgKHkODEPou5/AwboaGRPEFYULOyYeI0HiDFzpK0G6de+7Q==", - "dev": true, "dependencies": { "@aws-crypto/sha256-browser": "2.0.0", "@aws-crypto/sha256-js": "2.0.0", @@ -422,7 +414,6 @@ "version": "3.112.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.112.0.tgz", "integrity": "sha512-hSApRO2wg3jk9VRGM6SCZO3aFP7DKVSUqs6FrvlXlj+JU88ZKObjrGE61cCzXoD89Dh+b9t8A2T6W51Nzriaxw==", - "dev": true, "dependencies": { "@aws-crypto/sha256-browser": "2.0.0", "@aws-crypto/sha256-js": "2.0.0", @@ -469,7 +460,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.110.0.tgz", "integrity": "sha512-7VvtKy4CL63BAktQ2vgsjhWDSXpkXO5YdiI56LQnHztrvSuJBBaxJ7R1p/k0b2tEUhYKUziAIW8EKE/7EGPR4g==", - "dev": true, "dependencies": { "@aws-sdk/signature-v4": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -485,7 +475,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.110.0.tgz", "integrity": "sha512-oFU3IYk/Bl5tdsz1qigtm3I25a9cvXPqlE8VjYjxVDdLujF5zd/4HLbhP4GQWhpEwZmM1ijcSNfLcyywVevTZg==", - "dev": true, "dependencies": { "@aws-sdk/property-provider": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -499,7 +488,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.110.0.tgz", "integrity": "sha512-atl+7/dAB+8fG9XI2fYyCgXKYDbOzot65VAwis+14bOEUCVp7PCJifBEZ/L8GEq564p+Fa2p1IpV0wuQXxqFUQ==", - "dev": true, "dependencies": { "@aws-sdk/node-config-provider": "3.110.0", "@aws-sdk/property-provider": "3.110.0", @@ -515,7 +503,6 @@ "version": "3.112.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.112.0.tgz", "integrity": "sha512-ebgZ6/jZdTGHQ3zfq/ccmS+7YmLk6yUWHDmh69VK+B1Dd+S1jFwbD9EQ+pYWCp/gEl9F620NSwb6KghRylPWEQ==", - "dev": true, "dependencies": { "@aws-sdk/credential-provider-env": "3.110.0", "@aws-sdk/credential-provider-imds": "3.110.0", @@ -534,7 +521,6 @@ "version": "3.112.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.112.0.tgz", "integrity": "sha512-7txS7P3BAaU4cksFw/PnoVskVvO8h/TPvOl/BxFtCiUdwA6FRltLvBeMlN08fwUoqgM6z06q8areBdeDqCHOSw==", - "dev": true, "dependencies": { "@aws-sdk/credential-provider-env": "3.110.0", "@aws-sdk/credential-provider-imds": "3.110.0", @@ -555,7 +541,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.110.0.tgz", "integrity": "sha512-JJcZePvRTfQHYj/+EEY13yItnZH/e8exlARFUjN0L13UrgHpOJtDQBa+YBHXo6MbTFQh+re25z2kzc+zOYSMNQ==", - "dev": true, "dependencies": { "@aws-sdk/property-provider": "3.110.0", "@aws-sdk/shared-ini-file-loader": "3.110.0", @@ -570,7 +555,6 @@ "version": "3.112.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.112.0.tgz", "integrity": "sha512-b6rOrSXbNK3fGyPvNpyF5zdktmAoNOqHCTmFSUcxRxOipyRGb5JACsbjWthIQkpWkpNCT8GFNLEg9spXPFIdLA==", - "dev": true, "dependencies": { "@aws-sdk/client-sso": "3.112.0", "@aws-sdk/property-provider": "3.110.0", @@ -586,7 +570,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.110.0.tgz", "integrity": "sha512-e4e5u7v3fsUFZsMcFMhMy1NdJBQpunYcLwpYlszm3OEICwTTekQ+hVvnVRd134doHvzepE4yp9sAop0Cj+IRVQ==", - "dev": true, "dependencies": { "@aws-sdk/property-provider": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -600,7 +583,6 @@ "version": "3.55.0", "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.55.0.tgz", "integrity": "sha512-kxDoHFDuQwZEEUZRp+ZLOg68EXuKPzUN86DcpIZantDVcmu7MSPTbbQp9DZd8MnKVEKCP7Sop5f7zCqOPl3LXw==", - "dev": true, "dependencies": { "mnemonist": "0.38.3", "tslib": "^2.3.1" @@ -613,7 +595,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.110.0.tgz", "integrity": "sha512-vk+K4GeCZL2J2rtvKO+T0Q7i3MDpEGZBMg5K2tj9sMcEQwty0BF0aFnP7Eu2l4/Zif2z1mWuUFM2WcZI6DVnbw==", - "dev": true, "dependencies": { "@aws-sdk/protocol-http": "3.110.0", "@aws-sdk/querystring-builder": "3.110.0", @@ -626,7 +607,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.110.0.tgz", "integrity": "sha512-wakl+kP2O8wTGYiQ3InZy+CVfGrIpFfq9fo4zif9PZac0BbUbguUU1dkY34uZiaf+4o2/9MoDYrHU2HYeXKxWw==", - "dev": true, "dependencies": { "@aws-sdk/types": "3.110.0", "@aws-sdk/util-buffer-from": "3.55.0", @@ -640,7 +620,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.110.0.tgz", "integrity": "sha512-O8J1InmtJkoiUMbQDtxBfOzgigBp9iSVsNXQrhs2qHh3826cJOfE7NGT3u+NMw73Pk5j2cfmOh1+7k/76IqxOg==", - "dev": true, "dependencies": { "@aws-sdk/types": "3.110.0", "tslib": "^2.3.1" @@ -650,7 +629,6 @@ "version": "3.55.0", "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.55.0.tgz", "integrity": "sha512-NbiPHVYuPxdqdFd6FxzzN3H1BQn/iWA3ri3Ry7AyLeP/tGs1yzEWMwf8BN8TSMALI0GXT6Sh0GDWy3Ok5xB6DA==", - "dev": true, "dependencies": { "tslib": "^2.3.1" }, @@ -658,11 +636,27 @@ "node": ">= 12.0.0" } }, + "node_modules/@aws-sdk/lib-dynamodb": { + "version": "3.208.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.208.0.tgz", + "integrity": "sha512-Cr1eR7JqSe3wM3KQFrn0+ePwb5tjn9g+7q74zM19caBC3IvQUegmWnCV3gG0KlVo18U6veJiUSIDi3fZDAXSdQ==", + "dependencies": { + "@aws-sdk/util-dynamodb": "3.208.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-dynamodb": "^3.0.0", + "@aws-sdk/smithy-client": "^3.0.0", + "@aws-sdk/types": "^3.0.0" + } + }, "node_modules/@aws-sdk/middleware-content-length": { "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.110.0.tgz", "integrity": "sha512-hKU+zdqfAJQg22LXMVu/z35nNIHrVAKpVKPe9+WYVdL/Z7JKUPK7QymqKGOyDuDbzW6OxyulC1zKGEX12zGmdA==", - "dev": true, "dependencies": { "@aws-sdk/protocol-http": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -676,7 +670,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.110.0.tgz", "integrity": "sha512-GUnNcuEBqD21E8EgevTcaBXJGnH5dp7eDSfWceYJP+iSscFXLzFFOf1I6H0cwvfARVMHVvlFz0tQcojCSHUZig==", - "dev": true, "dependencies": { "@aws-sdk/config-resolver": "3.110.0", "@aws-sdk/endpoint-cache": "3.55.0", @@ -692,7 +685,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.110.0.tgz", "integrity": "sha512-/Cknn1vL2LTlclI0MX2RzmtdPlCJ5palCRXxm/mod1oHwg4oNTKRlUX3LUD+L8g7JuJ4h053Ch9KS/A0vanE5Q==", - "dev": true, "dependencies": { "@aws-sdk/protocol-http": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -706,7 +698,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.110.0.tgz", "integrity": "sha512-+pz+a+8dfTnzLj79nHrv3aONMp/N36/erMd+7JXeR84QEosVLrFBUwKA8x5x6O3s1iBbQzRKMYEIuja9xn1BPA==", - "dev": true, "dependencies": { "@aws-sdk/types": "3.110.0", "tslib": "^2.3.1" @@ -719,7 +710,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.110.0.tgz", "integrity": "sha512-Wav782zd7bcd1e6txRob76CDOdVOaUQ8HXoywiIm/uFrEEUZvhs2mgnXjVUVCMBUehdNgnL99z420aS13JeL/Q==", - "dev": true, "dependencies": { "@aws-sdk/protocol-http": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -733,7 +723,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.110.0.tgz", "integrity": "sha512-lwLAQQveCiUqymQvVYjCee6QOXw3Zqbc9yq+pxYdXbs1Cv1XMA6PeJeUU5r5KEVuSceBLyyrnl6E0R1l1om1MQ==", - "dev": true, "dependencies": { "@aws-sdk/protocol-http": "3.110.0", "@aws-sdk/service-error-classification": "3.110.0", @@ -750,7 +739,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.110.0.tgz", "integrity": "sha512-EjY/YFdlr5jECde6qIrTIyGBbn/34CKcQGKvmvRd31+3qaClIJLAwNuHfcVzWvCUGbAslsfvdbOpLju33pSQRA==", - "dev": true, "dependencies": { "@aws-sdk/middleware-signing": "3.110.0", "@aws-sdk/property-provider": "3.110.0", @@ -767,7 +755,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.110.0.tgz", "integrity": "sha512-brVupxgEAmcZ9cZvdHEH8zncjvGKIiud8pOe4fiimp5NpHmjBLew4jUbnOKNZNAjaidcKUtz//cxtutD6yXEww==", - "dev": true, "dependencies": { "@aws-sdk/types": "3.110.0", "tslib": "^2.3.1" @@ -780,7 +767,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.110.0.tgz", "integrity": "sha512-y6ZKrGYfgDlFMzWhZmoq5J1UctBgZOUvMmnU9sSeZ020IlEPiOxFMvR0Zu6TcYThp8uy3P0wyjQtGYeTl9Z/kA==", - "dev": true, "dependencies": { "@aws-sdk/property-provider": "3.110.0", "@aws-sdk/protocol-http": "3.110.0", @@ -796,7 +782,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.110.0.tgz", "integrity": "sha512-iaLHw6ctOuGa9UxNueU01Xes+15dR+mqioRpUOUZ9Zx+vhXVpD7C8lnNqhRnYeFXs10/rNIzASgsIrAHTlnlIQ==", - "dev": true, "dependencies": { "tslib": "^2.3.1" }, @@ -808,7 +793,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.110.0.tgz", "integrity": "sha512-Y6FgiZr99DilYq6AjeaaWcNwVlSQpNGKrILzvV4Tmz03OaBIspe4KL+8EZ2YA/sAu5Lpw80vItdezqDOwGAlnQ==", - "dev": true, "dependencies": { "@aws-sdk/protocol-http": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -822,7 +806,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.110.0.tgz", "integrity": "sha512-46p4dCPGYctuybTQTwLpjenA1QFHeyJw/OyggGbtUJUy+833+ldnAwcPVML2aXJKUKv3APGI8vq1kaloyNku3Q==", - "dev": true, "dependencies": { "@aws-sdk/property-provider": "3.110.0", "@aws-sdk/shared-ini-file-loader": "3.110.0", @@ -837,7 +820,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.110.0.tgz", "integrity": "sha512-/rP+hY516DpP8fZhwFW5xM/ElH0w6lxw/15VvZCoY5EnOLAF5XIsJdzscWPSEW2FHCylBM4SNrKhGar14BDXhA==", - "dev": true, "dependencies": { "@aws-sdk/abort-controller": "3.110.0", "@aws-sdk/protocol-http": "3.110.0", @@ -853,7 +835,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.110.0.tgz", "integrity": "sha512-7NkpmYeOkK3mhWBNU+/zSDqwzeaSPH1qrq4L//WV7WS/weYyE/jusQeZoOxVsuZQnQEXHt5O2hKVeUwShl12xA==", - "dev": true, "dependencies": { "@aws-sdk/types": "3.110.0", "tslib": "^2.3.1" @@ -866,7 +847,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.110.0.tgz", "integrity": "sha512-qdi2gCbJiyPyLn+afebPNp/5nVCRh1X7t7IRIFl3FHVEC+o54u/ojay/MLZ4M/+X9Fa4Zxsb0Wpp3T0xAHVDBg==", - "dev": true, "dependencies": { "@aws-sdk/types": "3.110.0", "tslib": "^2.3.1" @@ -879,7 +859,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.110.0.tgz", "integrity": "sha512-7V3CDXj519izmbBn9ZE68ymASwGriA+Aq+cb/yHSVtffnvXjPtvONNw7G/5iVblisGLSCUe2hSvpYtcaXozbHw==", - "dev": true, "dependencies": { "@aws-sdk/types": "3.110.0", "@aws-sdk/util-uri-escape": "3.55.0", @@ -893,7 +872,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.110.0.tgz", "integrity": "sha512-//pJHH7hrhdDMZGBPKXKymmC/tJM7gFT0w/qbu/yd3Wm4W2fMB+8gkmj6EZctx7jrsWlfRQuvFejKqEfapur/g==", - "dev": true, "dependencies": { "@aws-sdk/types": "3.110.0", "tslib": "^2.3.1" @@ -914,7 +892,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.110.0.tgz", "integrity": "sha512-E1ERoqEoG206XNBYWCKLgHkzCbTxdpDEGbsLET2DnvjFsT0s9p2dPvVux3bYl7JVAhyGduE+qcqWk7MzhFCBNQ==", - "dev": true, "dependencies": { "tslib": "^2.3.1" }, @@ -926,7 +903,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.110.0.tgz", "integrity": "sha512-utxxdllOnmQDhbpipnFAbuQ4c2pwefZ+2hi48jKvQRULQ2PO4nxLmdZm6B0FXaTijbKsyO7GrMik+EZ6mi3ARQ==", - "dev": true, "dependencies": { "@aws-sdk/is-array-buffer": "3.55.0", "@aws-sdk/types": "3.110.0", @@ -943,7 +919,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.110.0.tgz", "integrity": "sha512-gNLYrmdAe/1hVF2Nv2LF4OkL1A0a1o708pEMZHzql9xP164omRDaLrGDhz9tH7tsJEgLz+Bf4E8nTuISeDwvGg==", - "dev": true, "dependencies": { "@aws-sdk/middleware-stack": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -965,7 +940,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.110.0.tgz", "integrity": "sha512-tILFB8/Q73yzgO0dErJNnELmmBszd0E6FucwAnG3hfDefjqCBe09Q/1yhu2aARXyRmZa4AKp0sWcdwIWHc8dnA==", - "dev": true, "dependencies": { "@aws-sdk/querystring-parser": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -976,7 +950,6 @@ "version": "3.109.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64-browser/-/util-base64-browser-3.109.0.tgz", "integrity": "sha512-lAZ6fyDGiRLaIsKT9qh7P9FGuNyZ4gAbr1YOSQk/5mHtaTuUvxlPptZuInNM/0MPQm6lpcot00D8IWTucn4PbA==", - "dev": true, "dependencies": { "tslib": "^2.3.1" } @@ -985,7 +958,6 @@ "version": "3.55.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64-node/-/util-base64-node-3.55.0.tgz", "integrity": "sha512-UQ/ZuNoAc8CFMpSiRYmevaTsuRKzLwulZTnM8LNlIt9Wx1tpNvqp80cfvVj7yySKROtEi20wq29h31dZf1eYNQ==", - "dev": true, "dependencies": { "@aws-sdk/util-buffer-from": "3.55.0", "tslib": "^2.3.1" @@ -998,7 +970,6 @@ "version": "3.55.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.55.0.tgz", "integrity": "sha512-Ei2OCzXQw5N6ZkTMZbamUzc1z+z1R1Ja5tMEagz5BxuX4vWdBObT+uGlSzL8yvTbjoPjnxWA2aXyEqaUP3JS8Q==", - "dev": true, "dependencies": { "tslib": "^2.3.1" } @@ -1007,7 +978,6 @@ "version": "3.55.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.55.0.tgz", "integrity": "sha512-lU1d4I+9wJwydduXs0SxSfd+mHKjxeyd39VwOv6i2KSwWkPbji9UQqpflKLKw+r45jL7+xU/zfeTUg5Tt/3Gew==", - "dev": true, "dependencies": { "tslib": "^2.3.1" }, @@ -1019,7 +989,6 @@ "version": "3.55.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.55.0.tgz", "integrity": "sha512-uVzKG1UgvnV7XX2FPTylBujYMKBPBaq/qFBxfl0LVNfrty7YjpfieQxAe6yRLD+T0Kir/WDQwGvYC+tOYG3IGA==", - "dev": true, "dependencies": { "@aws-sdk/is-array-buffer": "3.55.0", "tslib": "^2.3.1" @@ -1032,7 +1001,6 @@ "version": "3.109.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.109.0.tgz", "integrity": "sha512-GrAZl/aBv0A28LkyNyq8SPJ5fmViCwz80fWLMeWx/6q5AbivuILogjlWwEZSvZ9zrlHOcFC0+AnCa5pQrjaslw==", - "dev": true, "dependencies": { "tslib": "^2.3.1" }, @@ -1044,7 +1012,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.110.0.tgz", "integrity": "sha512-Y2dcOOD20S3bv/IjUqpdKIiDt6995SXNG5Pu/LeSdXNyLCOIm9rX4gHTxl9fC1KK5M/gR9fGJ362f67WwqEEqw==", - "dev": true, "dependencies": { "@aws-sdk/property-provider": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -1059,7 +1026,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.110.0.tgz", "integrity": "sha512-Cr3Z5nyrw1KowjbW76xp8hkT/zJtYjAVZ9PS4l84KxIicbVvDOBpxG3yNddkuQcavmlH6G4wH9uM5DcnpKDncg==", - "dev": true, "dependencies": { "@aws-sdk/config-resolver": "3.110.0", "@aws-sdk/credential-provider-imds": "3.110.0", @@ -1072,11 +1038,21 @@ "node": ">= 10.0.0" } }, + "node_modules/@aws-sdk/util-dynamodb": { + "version": "3.208.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.208.0.tgz", + "integrity": "sha512-4tJNlsZ2wpaQVxQ+AwXGmUk3lLWBrqK4lpJYITJ1C6Y8VZF/yqjeH+mNGQifMzO3T4dzCuGBCUKJ1HUCmGApCw==", + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@aws-sdk/util-hex-encoding": { "version": "3.109.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.109.0.tgz", "integrity": "sha512-s8CgTNrn3cLkrdiohfxLuOYPCanzvHn/aH5RW6DaMoeQiG5Hl9QUiP/WtdQ9QQx3xvpQFpmvxIaSBwSgFNLQxA==", - "dev": true, "dependencies": { "tslib": "^2.3.1" }, @@ -1088,7 +1064,6 @@ "version": "3.55.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.55.0.tgz", "integrity": "sha512-0sPmK2JaJE2BbTcnvybzob/VrFKCXKfN4CUKcvn0yGg/me7Bz+vtzQRB3Xp+YSx+7OtWxzv63wsvHoAnXvgxgg==", - "dev": true, "dependencies": { "tslib": "^2.3.1" }, @@ -1100,7 +1075,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.110.0.tgz", "integrity": "sha512-PTVWrI5fA9d5hHJs6RzX2dIS2jRQ3uW073Fm0BePpQeDdZrEk+S5KNwRhUtpN6sdSV45vm6S9rrjZUG51qwGmA==", - "dev": true, "dependencies": { "tslib": "^2.3.1" }, @@ -1112,7 +1086,6 @@ "version": "3.55.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.55.0.tgz", "integrity": "sha512-mmdDLUpFCN2nkfwlLdOM54lTD528GiGSPN1qb8XtGLgZsJUmg3uJSFIN2lPeSbEwJB3NFjVas/rnQC48i7mV8w==", - "dev": true, "dependencies": { "tslib": "^2.3.1" }, @@ -1124,7 +1097,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.110.0.tgz", "integrity": "sha512-rNdhmHDMV5dNJctqlBWimkZLJRB+x03DB+61pm+SKSFk6gPIVIvc1WNXqDFphkiswT4vA13ZUkGHzt+N4+noQQ==", - "dev": true, "dependencies": { "@aws-sdk/types": "3.110.0", "bowser": "^2.11.0", @@ -1135,7 +1107,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.110.0.tgz", "integrity": "sha512-OQ915TPCCBwZWz5Np8zkNWn7U6KvrTZfFoCOy/VIemK3dUqmnBZ7HqGpuZx8SwJ2R9JE1x+j0niYSJ5fWJZZKA==", - "dev": true, "dependencies": { "@aws-sdk/node-config-provider": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -1149,7 +1120,6 @@ "version": "3.109.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.109.0.tgz", "integrity": "sha512-FmcGSz0v7Bqpl1SE8G1Gc0CtDpug+rvqNCG/szn86JApD/f5x8oByjbEiAyTU2ZH2VevUntx6EW68ulHyH+x+w==", - "dev": true, "dependencies": { "tslib": "^2.3.1" } @@ -1158,7 +1128,6 @@ "version": "3.109.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-node/-/util-utf8-node-3.109.0.tgz", "integrity": "sha512-Ti/ZBdvz2eSTElsucjzNmzpyg2MwfD1rXmxD0hZuIF8bPON/0+sZYnWd5CbDw9kgmhy28dmKue086tbZ1G0iLQ==", - "dev": true, "dependencies": { "@aws-sdk/util-buffer-from": "3.55.0", "tslib": "^2.3.1" @@ -1171,7 +1140,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-waiter/-/util-waiter-3.110.0.tgz", "integrity": "sha512-8dE6W6XYfjk1gx/aeb8NeLfMMLkLFhlV1lmKpFSBJhY8msajU8aQahTuykq5JW8QT/wCGbqbu7dH35SdX7kO+A==", - "dev": true, "dependencies": { "@aws-sdk/abort-controller": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -2244,6 +2212,27 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/@jest/expect-utils": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-28.1.3.tgz", + "integrity": "sha512-wvbi9LUrHJLn3NlDW6wF2hvIMtd4JUl2QNVrjq+IBSHirgfrR3o9RnVtxzdEGO2n9JyIWwHnLfby5KzqBGg2YA==", + "dev": true, + "dependencies": { + "jest-get-type": "^28.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/expect-utils/node_modules/jest-get-type": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", + "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, "node_modules/@jest/fake-timers": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", @@ -2319,6 +2308,18 @@ } } }, + "node_modules/@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.24.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, "node_modules/@jest/source-map": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", @@ -3748,6 +3749,12 @@ "@octokit/openapi-types": "^11.2.0" } }, + "node_modules/@sinclair/typebox": { + "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", + "dev": true + }, "node_modules/@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -3766,6 +3773,23 @@ "@sinonjs/commons": "^1.7.0" } }, + "node_modules/@sinonjs/samsam": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.3.tgz", + "integrity": "sha512-nhOb2dWPeb1sd3IQXL/dVPnKHDOAFfvichtBf4xV00/rU1QbPCQqKMbvIheIjqwVjh7qIgf2AHTHi391yMOMpQ==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", + "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", + "dev": true + }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -3992,6 +4016,21 @@ "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", "dev": true }, + "node_modules/@types/sinon": { + "version": "10.0.13", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.13.tgz", + "integrity": "sha512-UVjDqJblVNQYvVNUsj0PuYYw0ELRmgt1Nt5Vk0pT5f16ROGfcKJY8o1HVuMOJOpD727RrGB9EGvoaTQE5tgxZQ==", + "dev": true, + "dependencies": { + "@types/sinonjs__fake-timers": "*" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", + "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", + "dev": true + }, "node_modules/@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -4970,6 +5009,200 @@ "node": ">= 10.0.0" } }, + "node_modules/aws-sdk-client-mock": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aws-sdk-client-mock/-/aws-sdk-client-mock-2.0.0.tgz", + "integrity": "sha512-yjC39Ud78Cgwu9jLc7LoFILT8xtyvR9doCfd8tjeqaOI4oQ5IeTaIYDezWpWKndmrjXZzVLw/odWKP1hpuvsVQ==", + "dev": true, + "dependencies": { + "@types/sinon": "^10.0.10", + "sinon": "^11.1.1", + "tslib": "^2.1.0" + } + }, + "node_modules/aws-sdk-client-mock-jest": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aws-sdk-client-mock-jest/-/aws-sdk-client-mock-jest-2.0.0.tgz", + "integrity": "sha512-HwJeJThngXDUyyyd3Hk12Ailu3smhQzyox+nrF14TxE/LNSJsSmJ2rXahzj7Zdyxn9jDSe2h2ulrfUNYgbPYlw==", + "dev": true, + "dependencies": { + "@types/jest": "^28.1.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "aws-sdk-client-mock": "2.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/@types/jest": { + "version": "28.1.8", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-28.1.8.tgz", + "integrity": "sha512-8TJkV++s7B6XqnDrzR1m/TT0A0h948Pnl/097veySPN67VRAgQ4gZ7n2KfJo2rVq6njQjdxU3GCCyDvAeuHoiw==", + "dev": true, + "dependencies": { + "expect": "^28.0.0", + "pretty-format": "^28.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/@types/yargs": { + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/diff-sequences": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", + "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/expect": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/expect/-/expect-28.1.3.tgz", + "integrity": "sha512-eEh0xn8HlsuOBxFgIss+2mX85VAS4Qy3OSkjV7rlBWljtA4oWH37glVGyOZSZvErDT/yBywZdPGwCXuTvSG85g==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^28.1.3", + "jest-get-type": "^28.0.2", + "jest-matcher-utils": "^28.1.3", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/jest-diff": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", + "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^28.1.1", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/jest-get-type": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", + "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/jest-matcher-utils": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", + "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^28.1.3", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/jest-message-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", + "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^28.1.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/jest-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", + "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, "node_modules/aws-sdk/node_modules/uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", @@ -5214,8 +5447,7 @@ "node_modules/bowser": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", - "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", - "dev": true + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" }, "node_modules/brace-expansion": { "version": "1.1.11", @@ -7188,7 +7420,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -8280,7 +8511,6 @@ "version": "3.19.0", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.19.0.tgz", "integrity": "sha512-4pXwmBplsCPv8FOY1WRakF970TjNGnGnfbOnLqjlYvMiF1SR3yOHyxMR/YCXpPTOspNF5gwudqktIP4VsWkvBg==", - "dev": true, "bin": { "xml2js": "cli.js" }, @@ -10747,6 +10977,12 @@ "node": ">=0.6.0" } }, + "node_modules/just-extend": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "dev": true + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -11082,6 +11318,12 @@ "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", "dev": true }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "dev": true + }, "node_modules/lodash.ismatch": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", @@ -11654,7 +11896,6 @@ "version": "0.38.3", "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.3.tgz", "integrity": "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==", - "dev": true, "dependencies": { "obliterator": "^1.6.1" } @@ -11738,6 +11979,46 @@ "node": ">= 0.4.0" } }, + "node_modules/nise": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.2.tgz", + "integrity": "sha512-+gQjFi8v+tkfCuSCxfURHLhRhniE/+IaYbIphxAN2JRR9SHKhY8hgXpaXiYfHdw+gcGe4buxgbprBQFab9FkhA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^2.0.0", + "@sinonjs/fake-timers": "^7.0.4", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "node_modules/nise/node_modules/@sinonjs/commons": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/nise/node_modules/@sinonjs/fake-timers": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz", + "integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/nise/node_modules/@sinonjs/fake-timers/node_modules/@sinonjs/commons": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.5.tgz", + "integrity": "sha512-rTpCA0wG1wUxglBSFdMMY0oTrKYvgf4fNgv/sXbfCVAdf+FnPBdKJR/7XbpTCwbCrvCbdPYnlWaUUYz4V2fPDA==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, "node_modules/node-fetch": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", @@ -12270,8 +12551,7 @@ "node_modules/obliterator": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-1.6.1.tgz", - "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==", - "dev": true + "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==" }, "node_modules/once": { "version": "1.4.0", @@ -12696,6 +12976,21 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/path-to-regexp/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -13795,12 +14090,39 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sinon": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.2.tgz", + "integrity": "sha512-59237HChms4kg7/sXhiRcUzdSkKuydDeTiamT/jesUVHshBgL8XAmhgFo0GfK6RruMDM/iRSij1EybmMog9cJw==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.8.3", + "@sinonjs/fake-timers": "^7.1.2", + "@sinonjs/samsam": "^6.0.2", + "diff": "^5.0.0", + "nise": "^5.1.0", + "supports-color": "^7.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/sinon/node_modules/@sinonjs/fake-timers": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz", + "integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -14672,8 +14994,7 @@ "node_modules/tslib": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -14966,7 +15287,6 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, "bin": { "uuid": "dist/bin/uuid" } @@ -15542,14 +15862,27 @@ }, "packages/commons": { "name": "@aws-lambda-powertools/commons", - "version": "1.4.0", + "version": "1.4.1", "license": "MIT-0" }, + "packages/idempotency": { + "version": "0.0.11", + "license": "MIT", + "dependencies": { + "@aws-lambda-powertools/commons": "^1.4.1", + "@aws-sdk/lib-dynamodb": "^3.170.0" + }, + "devDependencies": { + "aws-sdk-client-mock": "^2.0.0", + "aws-sdk-client-mock-jest": "^2.0.0" + } + }, "packages/logger": { "name": "@aws-lambda-powertools/logger", - "version": "1.4.0", + "version": "1.4.1", "license": "MIT", "dependencies": { + "@aws-lambda-powertools/commons": "^1.4.1", "lodash.clonedeep": "^4.5.0", "lodash.merge": "^4.6.2", "lodash.pickby": "^4.6.0" @@ -15562,8 +15895,11 @@ }, "packages/metrics": { "name": "@aws-lambda-powertools/metrics", - "version": "1.4.0", + "version": "1.4.1", "license": "MIT-0", + "dependencies": { + "@aws-lambda-powertools/commons": "^1.4.1" + }, "devDependencies": { "@types/promise-retry": "^1.1.3", "promise-retry": "^2.0.1" @@ -15571,9 +15907,10 @@ }, "packages/tracer": { "name": "@aws-lambda-powertools/tracer", - "version": "1.4.0", + "version": "1.4.1", "license": "MIT-0", "dependencies": { + "@aws-lambda-powertools/commons": "^1.4.1", "aws-xray-sdk-core": "^3.3.6" }, "devDependencies": { @@ -15702,7 +16039,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-2.0.0.tgz", "integrity": "sha512-pkVXf/dq6PITJ0jzYZ69VhL8VFOFoPZLZqtU/12SGnzYuJOOGNfF41q9GxdI1yqC8R13Rq3jOLKDFpUJFT5eTA==", - "dev": true, "requires": { "tslib": "^1.11.1" }, @@ -15710,8 +16046,7 @@ "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" } } }, @@ -15719,7 +16054,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-2.0.0.tgz", "integrity": "sha512-rYXOQ8BFOaqMEHJrLHul/25ckWH6GTJtdLSajhlqGMx0PmSueAuvboCuZCTqEKlxR8CQOwRarxYMZZSYlhRA1A==", - "dev": true, "requires": { "@aws-crypto/ie11-detection": "^2.0.0", "@aws-crypto/sha256-js": "^2.0.0", @@ -15734,8 +16068,7 @@ "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" } } }, @@ -15743,7 +16076,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-2.0.0.tgz", "integrity": "sha512-VZY+mCY4Nmrs5WGfitmNqXzaE873fcIZDu54cbaDaaamsaTOP1DBImV9F4pICc3EHjQXujyE8jig+PFCaew9ig==", - "dev": true, "requires": { "@aws-crypto/util": "^2.0.0", "@aws-sdk/types": "^3.1.0", @@ -15753,8 +16085,7 @@ "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" } } }, @@ -15762,7 +16093,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-2.0.0.tgz", "integrity": "sha512-Ge7WQ3E0OC7FHYprsZV3h0QIcpdyJLvIeg+uTuHqRYm8D6qCFJoiC+edSzSyFiHtZf+NOQDJ1q46qxjtzIY2nA==", - "dev": true, "requires": { "tslib": "^1.11.1" }, @@ -15770,8 +16100,7 @@ "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" } } }, @@ -15779,7 +16108,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-2.0.1.tgz", "integrity": "sha512-JJmFFwvbm08lULw4Nm5QOLg8+lAQeC8aCXK5xrtxntYzYXCGfHwUJ4Is3770Q7HmICsXthGQ+ZsDL7C2uH3yBQ==", - "dev": true, "requires": { "@aws-sdk/types": "^3.1.0", "@aws-sdk/util-utf8-browser": "^3.0.0", @@ -15789,17 +16117,26 @@ "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" } } }, "@aws-lambda-powertools/commons": { "version": "file:packages/commons" }, + "@aws-lambda-powertools/idempotency": { + "version": "file:packages/idempotency", + "requires": { + "@aws-lambda-powertools/commons": "^1.4.1", + "@aws-sdk/lib-dynamodb": "^3.170.0", + "aws-sdk-client-mock": "^2.0.0", + "aws-sdk-client-mock-jest": "^2.0.0" + } + }, "@aws-lambda-powertools/logger": { "version": "file:packages/logger", "requires": { + "@aws-lambda-powertools/commons": "^1.4.1", "@types/lodash.clonedeep": "^4.5.7", "@types/lodash.merge": "^4.6.7", "@types/lodash.pickby": "^4.6.7", @@ -15811,6 +16148,7 @@ "@aws-lambda-powertools/metrics": { "version": "file:packages/metrics", "requires": { + "@aws-lambda-powertools/commons": "^1.4.1", "@types/promise-retry": "^1.1.3", "promise-retry": "^2.0.1" } @@ -15818,6 +16156,7 @@ "@aws-lambda-powertools/tracer": { "version": "file:packages/tracer", "requires": { + "@aws-lambda-powertools/commons": "^1.4.1", "@aws-sdk/client-dynamodb": "^3.100.0", "@types/promise-retry": "^1.1.3", "aws-xray-sdk-core": "^3.3.6", @@ -15829,7 +16168,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.110.0.tgz", "integrity": "sha512-zok/WEVuK7Jh6V9YeA56pNZtxUASon9LTkS7vE65A4UFmNkPGNBCNgoiBcbhWfxwrZ8wtXcQk6rtUut39831mA==", - "dev": true, "requires": { "@aws-sdk/types": "3.110.0", "tslib": "^2.3.1" @@ -15839,7 +16177,6 @@ "version": "3.113.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.113.0.tgz", "integrity": "sha512-tp0/smnSBqoPdSbZqRaH46S9cDkOMXsbG8Qph+gV3+SL+V3nJLeGFzA+3WPmF0l0Bnv0/9Tms4ySZB0MsBSy/A==", - "dev": true, "requires": { "@aws-crypto/sha256-browser": "2.0.0", "@aws-crypto/sha256-js": "2.0.0", @@ -15884,7 +16221,6 @@ "version": "3.112.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.112.0.tgz", "integrity": "sha512-FwFmiapxuVQiyMdDaBvCpajnJkVWEUHBdO+7rIpzgKHkODEPou5/AwboaGRPEFYULOyYeI0HiDFzpK0G6de+7Q==", - "dev": true, "requires": { "@aws-crypto/sha256-browser": "2.0.0", "@aws-crypto/sha256-js": "2.0.0", @@ -15923,7 +16259,6 @@ "version": "3.112.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.112.0.tgz", "integrity": "sha512-hSApRO2wg3jk9VRGM6SCZO3aFP7DKVSUqs6FrvlXlj+JU88ZKObjrGE61cCzXoD89Dh+b9t8A2T6W51Nzriaxw==", - "dev": true, "requires": { "@aws-crypto/sha256-browser": "2.0.0", "@aws-crypto/sha256-js": "2.0.0", @@ -15967,7 +16302,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.110.0.tgz", "integrity": "sha512-7VvtKy4CL63BAktQ2vgsjhWDSXpkXO5YdiI56LQnHztrvSuJBBaxJ7R1p/k0b2tEUhYKUziAIW8EKE/7EGPR4g==", - "dev": true, "requires": { "@aws-sdk/signature-v4": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -15980,7 +16314,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.110.0.tgz", "integrity": "sha512-oFU3IYk/Bl5tdsz1qigtm3I25a9cvXPqlE8VjYjxVDdLujF5zd/4HLbhP4GQWhpEwZmM1ijcSNfLcyywVevTZg==", - "dev": true, "requires": { "@aws-sdk/property-provider": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -15991,7 +16324,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.110.0.tgz", "integrity": "sha512-atl+7/dAB+8fG9XI2fYyCgXKYDbOzot65VAwis+14bOEUCVp7PCJifBEZ/L8GEq564p+Fa2p1IpV0wuQXxqFUQ==", - "dev": true, "requires": { "@aws-sdk/node-config-provider": "3.110.0", "@aws-sdk/property-provider": "3.110.0", @@ -16004,7 +16336,6 @@ "version": "3.112.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.112.0.tgz", "integrity": "sha512-ebgZ6/jZdTGHQ3zfq/ccmS+7YmLk6yUWHDmh69VK+B1Dd+S1jFwbD9EQ+pYWCp/gEl9F620NSwb6KghRylPWEQ==", - "dev": true, "requires": { "@aws-sdk/credential-provider-env": "3.110.0", "@aws-sdk/credential-provider-imds": "3.110.0", @@ -16020,7 +16351,6 @@ "version": "3.112.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.112.0.tgz", "integrity": "sha512-7txS7P3BAaU4cksFw/PnoVskVvO8h/TPvOl/BxFtCiUdwA6FRltLvBeMlN08fwUoqgM6z06q8areBdeDqCHOSw==", - "dev": true, "requires": { "@aws-sdk/credential-provider-env": "3.110.0", "@aws-sdk/credential-provider-imds": "3.110.0", @@ -16038,7 +16368,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.110.0.tgz", "integrity": "sha512-JJcZePvRTfQHYj/+EEY13yItnZH/e8exlARFUjN0L13UrgHpOJtDQBa+YBHXo6MbTFQh+re25z2kzc+zOYSMNQ==", - "dev": true, "requires": { "@aws-sdk/property-provider": "3.110.0", "@aws-sdk/shared-ini-file-loader": "3.110.0", @@ -16050,7 +16379,6 @@ "version": "3.112.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.112.0.tgz", "integrity": "sha512-b6rOrSXbNK3fGyPvNpyF5zdktmAoNOqHCTmFSUcxRxOipyRGb5JACsbjWthIQkpWkpNCT8GFNLEg9spXPFIdLA==", - "dev": true, "requires": { "@aws-sdk/client-sso": "3.112.0", "@aws-sdk/property-provider": "3.110.0", @@ -16063,7 +16391,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.110.0.tgz", "integrity": "sha512-e4e5u7v3fsUFZsMcFMhMy1NdJBQpunYcLwpYlszm3OEICwTTekQ+hVvnVRd134doHvzepE4yp9sAop0Cj+IRVQ==", - "dev": true, "requires": { "@aws-sdk/property-provider": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -16074,7 +16401,6 @@ "version": "3.55.0", "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.55.0.tgz", "integrity": "sha512-kxDoHFDuQwZEEUZRp+ZLOg68EXuKPzUN86DcpIZantDVcmu7MSPTbbQp9DZd8MnKVEKCP7Sop5f7zCqOPl3LXw==", - "dev": true, "requires": { "mnemonist": "0.38.3", "tslib": "^2.3.1" @@ -16084,7 +16410,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.110.0.tgz", "integrity": "sha512-vk+K4GeCZL2J2rtvKO+T0Q7i3MDpEGZBMg5K2tj9sMcEQwty0BF0aFnP7Eu2l4/Zif2z1mWuUFM2WcZI6DVnbw==", - "dev": true, "requires": { "@aws-sdk/protocol-http": "3.110.0", "@aws-sdk/querystring-builder": "3.110.0", @@ -16097,7 +16422,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.110.0.tgz", "integrity": "sha512-wakl+kP2O8wTGYiQ3InZy+CVfGrIpFfq9fo4zif9PZac0BbUbguUU1dkY34uZiaf+4o2/9MoDYrHU2HYeXKxWw==", - "dev": true, "requires": { "@aws-sdk/types": "3.110.0", "@aws-sdk/util-buffer-from": "3.55.0", @@ -16108,7 +16432,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.110.0.tgz", "integrity": "sha512-O8J1InmtJkoiUMbQDtxBfOzgigBp9iSVsNXQrhs2qHh3826cJOfE7NGT3u+NMw73Pk5j2cfmOh1+7k/76IqxOg==", - "dev": true, "requires": { "@aws-sdk/types": "3.110.0", "tslib": "^2.3.1" @@ -16118,16 +16441,23 @@ "version": "3.55.0", "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.55.0.tgz", "integrity": "sha512-NbiPHVYuPxdqdFd6FxzzN3H1BQn/iWA3ri3Ry7AyLeP/tGs1yzEWMwf8BN8TSMALI0GXT6Sh0GDWy3Ok5xB6DA==", - "dev": true, "requires": { "tslib": "^2.3.1" } }, + "@aws-sdk/lib-dynamodb": { + "version": "3.208.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.208.0.tgz", + "integrity": "sha512-Cr1eR7JqSe3wM3KQFrn0+ePwb5tjn9g+7q74zM19caBC3IvQUegmWnCV3gG0KlVo18U6veJiUSIDi3fZDAXSdQ==", + "requires": { + "@aws-sdk/util-dynamodb": "3.208.0", + "tslib": "^2.3.1" + } + }, "@aws-sdk/middleware-content-length": { "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.110.0.tgz", "integrity": "sha512-hKU+zdqfAJQg22LXMVu/z35nNIHrVAKpVKPe9+WYVdL/Z7JKUPK7QymqKGOyDuDbzW6OxyulC1zKGEX12zGmdA==", - "dev": true, "requires": { "@aws-sdk/protocol-http": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -16138,7 +16468,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.110.0.tgz", "integrity": "sha512-GUnNcuEBqD21E8EgevTcaBXJGnH5dp7eDSfWceYJP+iSscFXLzFFOf1I6H0cwvfARVMHVvlFz0tQcojCSHUZig==", - "dev": true, "requires": { "@aws-sdk/config-resolver": "3.110.0", "@aws-sdk/endpoint-cache": "3.55.0", @@ -16151,7 +16480,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.110.0.tgz", "integrity": "sha512-/Cknn1vL2LTlclI0MX2RzmtdPlCJ5palCRXxm/mod1oHwg4oNTKRlUX3LUD+L8g7JuJ4h053Ch9KS/A0vanE5Q==", - "dev": true, "requires": { "@aws-sdk/protocol-http": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -16162,7 +16490,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.110.0.tgz", "integrity": "sha512-+pz+a+8dfTnzLj79nHrv3aONMp/N36/erMd+7JXeR84QEosVLrFBUwKA8x5x6O3s1iBbQzRKMYEIuja9xn1BPA==", - "dev": true, "requires": { "@aws-sdk/types": "3.110.0", "tslib": "^2.3.1" @@ -16172,7 +16499,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.110.0.tgz", "integrity": "sha512-Wav782zd7bcd1e6txRob76CDOdVOaUQ8HXoywiIm/uFrEEUZvhs2mgnXjVUVCMBUehdNgnL99z420aS13JeL/Q==", - "dev": true, "requires": { "@aws-sdk/protocol-http": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -16183,7 +16509,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.110.0.tgz", "integrity": "sha512-lwLAQQveCiUqymQvVYjCee6QOXw3Zqbc9yq+pxYdXbs1Cv1XMA6PeJeUU5r5KEVuSceBLyyrnl6E0R1l1om1MQ==", - "dev": true, "requires": { "@aws-sdk/protocol-http": "3.110.0", "@aws-sdk/service-error-classification": "3.110.0", @@ -16197,7 +16522,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.110.0.tgz", "integrity": "sha512-EjY/YFdlr5jECde6qIrTIyGBbn/34CKcQGKvmvRd31+3qaClIJLAwNuHfcVzWvCUGbAslsfvdbOpLju33pSQRA==", - "dev": true, "requires": { "@aws-sdk/middleware-signing": "3.110.0", "@aws-sdk/property-provider": "3.110.0", @@ -16211,7 +16535,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.110.0.tgz", "integrity": "sha512-brVupxgEAmcZ9cZvdHEH8zncjvGKIiud8pOe4fiimp5NpHmjBLew4jUbnOKNZNAjaidcKUtz//cxtutD6yXEww==", - "dev": true, "requires": { "@aws-sdk/types": "3.110.0", "tslib": "^2.3.1" @@ -16221,7 +16544,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.110.0.tgz", "integrity": "sha512-y6ZKrGYfgDlFMzWhZmoq5J1UctBgZOUvMmnU9sSeZ020IlEPiOxFMvR0Zu6TcYThp8uy3P0wyjQtGYeTl9Z/kA==", - "dev": true, "requires": { "@aws-sdk/property-provider": "3.110.0", "@aws-sdk/protocol-http": "3.110.0", @@ -16234,7 +16556,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.110.0.tgz", "integrity": "sha512-iaLHw6ctOuGa9UxNueU01Xes+15dR+mqioRpUOUZ9Zx+vhXVpD7C8lnNqhRnYeFXs10/rNIzASgsIrAHTlnlIQ==", - "dev": true, "requires": { "tslib": "^2.3.1" } @@ -16243,7 +16564,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.110.0.tgz", "integrity": "sha512-Y6FgiZr99DilYq6AjeaaWcNwVlSQpNGKrILzvV4Tmz03OaBIspe4KL+8EZ2YA/sAu5Lpw80vItdezqDOwGAlnQ==", - "dev": true, "requires": { "@aws-sdk/protocol-http": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -16254,7 +16574,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.110.0.tgz", "integrity": "sha512-46p4dCPGYctuybTQTwLpjenA1QFHeyJw/OyggGbtUJUy+833+ldnAwcPVML2aXJKUKv3APGI8vq1kaloyNku3Q==", - "dev": true, "requires": { "@aws-sdk/property-provider": "3.110.0", "@aws-sdk/shared-ini-file-loader": "3.110.0", @@ -16266,7 +16585,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.110.0.tgz", "integrity": "sha512-/rP+hY516DpP8fZhwFW5xM/ElH0w6lxw/15VvZCoY5EnOLAF5XIsJdzscWPSEW2FHCylBM4SNrKhGar14BDXhA==", - "dev": true, "requires": { "@aws-sdk/abort-controller": "3.110.0", "@aws-sdk/protocol-http": "3.110.0", @@ -16279,7 +16597,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.110.0.tgz", "integrity": "sha512-7NkpmYeOkK3mhWBNU+/zSDqwzeaSPH1qrq4L//WV7WS/weYyE/jusQeZoOxVsuZQnQEXHt5O2hKVeUwShl12xA==", - "dev": true, "requires": { "@aws-sdk/types": "3.110.0", "tslib": "^2.3.1" @@ -16289,7 +16606,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.110.0.tgz", "integrity": "sha512-qdi2gCbJiyPyLn+afebPNp/5nVCRh1X7t7IRIFl3FHVEC+o54u/ojay/MLZ4M/+X9Fa4Zxsb0Wpp3T0xAHVDBg==", - "dev": true, "requires": { "@aws-sdk/types": "3.110.0", "tslib": "^2.3.1" @@ -16299,7 +16615,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.110.0.tgz", "integrity": "sha512-7V3CDXj519izmbBn9ZE68ymASwGriA+Aq+cb/yHSVtffnvXjPtvONNw7G/5iVblisGLSCUe2hSvpYtcaXozbHw==", - "dev": true, "requires": { "@aws-sdk/types": "3.110.0", "@aws-sdk/util-uri-escape": "3.55.0", @@ -16310,7 +16625,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.110.0.tgz", "integrity": "sha512-//pJHH7hrhdDMZGBPKXKymmC/tJM7gFT0w/qbu/yd3Wm4W2fMB+8gkmj6EZctx7jrsWlfRQuvFejKqEfapur/g==", - "dev": true, "requires": { "@aws-sdk/types": "3.110.0", "tslib": "^2.3.1" @@ -16325,7 +16639,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.110.0.tgz", "integrity": "sha512-E1ERoqEoG206XNBYWCKLgHkzCbTxdpDEGbsLET2DnvjFsT0s9p2dPvVux3bYl7JVAhyGduE+qcqWk7MzhFCBNQ==", - "dev": true, "requires": { "tslib": "^2.3.1" } @@ -16334,7 +16647,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.110.0.tgz", "integrity": "sha512-utxxdllOnmQDhbpipnFAbuQ4c2pwefZ+2hi48jKvQRULQ2PO4nxLmdZm6B0FXaTijbKsyO7GrMik+EZ6mi3ARQ==", - "dev": true, "requires": { "@aws-sdk/is-array-buffer": "3.55.0", "@aws-sdk/types": "3.110.0", @@ -16348,7 +16660,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.110.0.tgz", "integrity": "sha512-gNLYrmdAe/1hVF2Nv2LF4OkL1A0a1o708pEMZHzql9xP164omRDaLrGDhz9tH7tsJEgLz+Bf4E8nTuISeDwvGg==", - "dev": true, "requires": { "@aws-sdk/middleware-stack": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -16364,7 +16675,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.110.0.tgz", "integrity": "sha512-tILFB8/Q73yzgO0dErJNnELmmBszd0E6FucwAnG3hfDefjqCBe09Q/1yhu2aARXyRmZa4AKp0sWcdwIWHc8dnA==", - "dev": true, "requires": { "@aws-sdk/querystring-parser": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -16375,7 +16685,6 @@ "version": "3.109.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64-browser/-/util-base64-browser-3.109.0.tgz", "integrity": "sha512-lAZ6fyDGiRLaIsKT9qh7P9FGuNyZ4gAbr1YOSQk/5mHtaTuUvxlPptZuInNM/0MPQm6lpcot00D8IWTucn4PbA==", - "dev": true, "requires": { "tslib": "^2.3.1" } @@ -16384,7 +16693,6 @@ "version": "3.55.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64-node/-/util-base64-node-3.55.0.tgz", "integrity": "sha512-UQ/ZuNoAc8CFMpSiRYmevaTsuRKzLwulZTnM8LNlIt9Wx1tpNvqp80cfvVj7yySKROtEi20wq29h31dZf1eYNQ==", - "dev": true, "requires": { "@aws-sdk/util-buffer-from": "3.55.0", "tslib": "^2.3.1" @@ -16394,7 +16702,6 @@ "version": "3.55.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.55.0.tgz", "integrity": "sha512-Ei2OCzXQw5N6ZkTMZbamUzc1z+z1R1Ja5tMEagz5BxuX4vWdBObT+uGlSzL8yvTbjoPjnxWA2aXyEqaUP3JS8Q==", - "dev": true, "requires": { "tslib": "^2.3.1" } @@ -16403,7 +16710,6 @@ "version": "3.55.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.55.0.tgz", "integrity": "sha512-lU1d4I+9wJwydduXs0SxSfd+mHKjxeyd39VwOv6i2KSwWkPbji9UQqpflKLKw+r45jL7+xU/zfeTUg5Tt/3Gew==", - "dev": true, "requires": { "tslib": "^2.3.1" } @@ -16412,7 +16718,6 @@ "version": "3.55.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.55.0.tgz", "integrity": "sha512-uVzKG1UgvnV7XX2FPTylBujYMKBPBaq/qFBxfl0LVNfrty7YjpfieQxAe6yRLD+T0Kir/WDQwGvYC+tOYG3IGA==", - "dev": true, "requires": { "@aws-sdk/is-array-buffer": "3.55.0", "tslib": "^2.3.1" @@ -16422,7 +16727,6 @@ "version": "3.109.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.109.0.tgz", "integrity": "sha512-GrAZl/aBv0A28LkyNyq8SPJ5fmViCwz80fWLMeWx/6q5AbivuILogjlWwEZSvZ9zrlHOcFC0+AnCa5pQrjaslw==", - "dev": true, "requires": { "tslib": "^2.3.1" } @@ -16431,7 +16735,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.110.0.tgz", "integrity": "sha512-Y2dcOOD20S3bv/IjUqpdKIiDt6995SXNG5Pu/LeSdXNyLCOIm9rX4gHTxl9fC1KK5M/gR9fGJ362f67WwqEEqw==", - "dev": true, "requires": { "@aws-sdk/property-provider": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -16443,7 +16746,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.110.0.tgz", "integrity": "sha512-Cr3Z5nyrw1KowjbW76xp8hkT/zJtYjAVZ9PS4l84KxIicbVvDOBpxG3yNddkuQcavmlH6G4wH9uM5DcnpKDncg==", - "dev": true, "requires": { "@aws-sdk/config-resolver": "3.110.0", "@aws-sdk/credential-provider-imds": "3.110.0", @@ -16453,11 +16755,18 @@ "tslib": "^2.3.1" } }, + "@aws-sdk/util-dynamodb": { + "version": "3.208.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.208.0.tgz", + "integrity": "sha512-4tJNlsZ2wpaQVxQ+AwXGmUk3lLWBrqK4lpJYITJ1C6Y8VZF/yqjeH+mNGQifMzO3T4dzCuGBCUKJ1HUCmGApCw==", + "requires": { + "tslib": "^2.3.1" + } + }, "@aws-sdk/util-hex-encoding": { "version": "3.109.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.109.0.tgz", "integrity": "sha512-s8CgTNrn3cLkrdiohfxLuOYPCanzvHn/aH5RW6DaMoeQiG5Hl9QUiP/WtdQ9QQx3xvpQFpmvxIaSBwSgFNLQxA==", - "dev": true, "requires": { "tslib": "^2.3.1" } @@ -16466,7 +16775,6 @@ "version": "3.55.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.55.0.tgz", "integrity": "sha512-0sPmK2JaJE2BbTcnvybzob/VrFKCXKfN4CUKcvn0yGg/me7Bz+vtzQRB3Xp+YSx+7OtWxzv63wsvHoAnXvgxgg==", - "dev": true, "requires": { "tslib": "^2.3.1" } @@ -16475,7 +16783,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.110.0.tgz", "integrity": "sha512-PTVWrI5fA9d5hHJs6RzX2dIS2jRQ3uW073Fm0BePpQeDdZrEk+S5KNwRhUtpN6sdSV45vm6S9rrjZUG51qwGmA==", - "dev": true, "requires": { "tslib": "^2.3.1" } @@ -16484,7 +16791,6 @@ "version": "3.55.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.55.0.tgz", "integrity": "sha512-mmdDLUpFCN2nkfwlLdOM54lTD528GiGSPN1qb8XtGLgZsJUmg3uJSFIN2lPeSbEwJB3NFjVas/rnQC48i7mV8w==", - "dev": true, "requires": { "tslib": "^2.3.1" } @@ -16493,7 +16799,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.110.0.tgz", "integrity": "sha512-rNdhmHDMV5dNJctqlBWimkZLJRB+x03DB+61pm+SKSFk6gPIVIvc1WNXqDFphkiswT4vA13ZUkGHzt+N4+noQQ==", - "dev": true, "requires": { "@aws-sdk/types": "3.110.0", "bowser": "^2.11.0", @@ -16504,7 +16809,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.110.0.tgz", "integrity": "sha512-OQ915TPCCBwZWz5Np8zkNWn7U6KvrTZfFoCOy/VIemK3dUqmnBZ7HqGpuZx8SwJ2R9JE1x+j0niYSJ5fWJZZKA==", - "dev": true, "requires": { "@aws-sdk/node-config-provider": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -16515,7 +16819,6 @@ "version": "3.109.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.109.0.tgz", "integrity": "sha512-FmcGSz0v7Bqpl1SE8G1Gc0CtDpug+rvqNCG/szn86JApD/f5x8oByjbEiAyTU2ZH2VevUntx6EW68ulHyH+x+w==", - "dev": true, "requires": { "tslib": "^2.3.1" } @@ -16524,7 +16827,6 @@ "version": "3.109.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-node/-/util-utf8-node-3.109.0.tgz", "integrity": "sha512-Ti/ZBdvz2eSTElsucjzNmzpyg2MwfD1rXmxD0hZuIF8bPON/0+sZYnWd5CbDw9kgmhy28dmKue086tbZ1G0iLQ==", - "dev": true, "requires": { "@aws-sdk/util-buffer-from": "3.55.0", "tslib": "^2.3.1" @@ -16534,7 +16836,6 @@ "version": "3.110.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-waiter/-/util-waiter-3.110.0.tgz", "integrity": "sha512-8dE6W6XYfjk1gx/aeb8NeLfMMLkLFhlV1lmKpFSBJhY8msajU8aQahTuykq5JW8QT/wCGbqbu7dH35SdX7kO+A==", - "dev": true, "requires": { "@aws-sdk/abort-controller": "3.110.0", "@aws-sdk/types": "3.110.0", @@ -17363,6 +17664,23 @@ "jest-mock": "^27.5.1" } }, + "@jest/expect-utils": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-28.1.3.tgz", + "integrity": "sha512-wvbi9LUrHJLn3NlDW6wF2hvIMtd4JUl2QNVrjq+IBSHirgfrR3o9RnVtxzdEGO2n9JyIWwHnLfby5KzqBGg2YA==", + "dev": true, + "requires": { + "jest-get-type": "^28.0.2" + }, + "dependencies": { + "jest-get-type": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", + "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "dev": true + } + } + }, "@jest/fake-timers": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", @@ -17421,6 +17739,15 @@ "v8-to-istanbul": "^8.1.0" } }, + "@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "dev": true, + "requires": { + "@sinclair/typebox": "^0.24.1" + } + }, "@jest/source-map": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", @@ -18608,6 +18935,12 @@ "@octokit/openapi-types": "^11.2.0" } }, + "@sinclair/typebox": { + "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", + "dev": true + }, "@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -18626,6 +18959,23 @@ "@sinonjs/commons": "^1.7.0" } }, + "@sinonjs/samsam": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.3.tgz", + "integrity": "sha512-nhOb2dWPeb1sd3IQXL/dVPnKHDOAFfvichtBf4xV00/rU1QbPCQqKMbvIheIjqwVjh7qIgf2AHTHi391yMOMpQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", + "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", + "dev": true + }, "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -18849,6 +19199,21 @@ "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", "dev": true }, + "@types/sinon": { + "version": "10.0.13", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.13.tgz", + "integrity": "sha512-UVjDqJblVNQYvVNUsj0PuYYw0ELRmgt1Nt5Vk0pT5f16ROGfcKJY8o1HVuMOJOpD727RrGB9EGvoaTQE5tgxZQ==", + "dev": true, + "requires": { + "@types/sinonjs__fake-timers": "*" + } + }, + "@types/sinonjs__fake-timers": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", + "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", + "dev": true + }, "@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -19547,6 +19912,166 @@ } } }, + "aws-sdk-client-mock": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aws-sdk-client-mock/-/aws-sdk-client-mock-2.0.0.tgz", + "integrity": "sha512-yjC39Ud78Cgwu9jLc7LoFILT8xtyvR9doCfd8tjeqaOI4oQ5IeTaIYDezWpWKndmrjXZzVLw/odWKP1hpuvsVQ==", + "dev": true, + "requires": { + "@types/sinon": "^10.0.10", + "sinon": "^11.1.1", + "tslib": "^2.1.0" + } + }, + "aws-sdk-client-mock-jest": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aws-sdk-client-mock-jest/-/aws-sdk-client-mock-jest-2.0.0.tgz", + "integrity": "sha512-HwJeJThngXDUyyyd3Hk12Ailu3smhQzyox+nrF14TxE/LNSJsSmJ2rXahzj7Zdyxn9jDSe2h2ulrfUNYgbPYlw==", + "dev": true, + "requires": { + "@types/jest": "^28.1.3", + "tslib": "^2.1.0" + }, + "dependencies": { + "@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "dev": true, + "requires": { + "@jest/schemas": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + } + }, + "@types/jest": { + "version": "28.1.8", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-28.1.8.tgz", + "integrity": "sha512-8TJkV++s7B6XqnDrzR1m/TT0A0h948Pnl/097veySPN67VRAgQ4gZ7n2KfJo2rVq6njQjdxU3GCCyDvAeuHoiw==", + "dev": true, + "requires": { + "expect": "^28.0.0", + "pretty-format": "^28.0.0" + } + }, + "@types/yargs": { + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", + "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + }, + "diff-sequences": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", + "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", + "dev": true + }, + "expect": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/expect/-/expect-28.1.3.tgz", + "integrity": "sha512-eEh0xn8HlsuOBxFgIss+2mX85VAS4Qy3OSkjV7rlBWljtA4oWH37glVGyOZSZvErDT/yBywZdPGwCXuTvSG85g==", + "dev": true, + "requires": { + "@jest/expect-utils": "^28.1.3", + "jest-get-type": "^28.0.2", + "jest-matcher-utils": "^28.1.3", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3" + } + }, + "jest-diff": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", + "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^28.1.1", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.3" + } + }, + "jest-get-type": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", + "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "dev": true + }, + "jest-matcher-utils": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", + "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^28.1.3", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.3" + } + }, + "jest-message-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", + "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^28.1.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", + "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "dev": true, + "requires": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dev": true, + "requires": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + } + }, + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + } + } + }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -19726,8 +20251,7 @@ "bowser": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", - "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", - "dev": true + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" }, "brace-expansion": { "version": "1.1.11", @@ -21431,8 +21955,7 @@ "entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" }, "env-paths": { "version": "2.2.1", @@ -22169,8 +22692,7 @@ "fast-xml-parser": { "version": "3.19.0", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.19.0.tgz", - "integrity": "sha512-4pXwmBplsCPv8FOY1WRakF970TjNGnGnfbOnLqjlYvMiF1SR3yOHyxMR/YCXpPTOspNF5gwudqktIP4VsWkvBg==", - "dev": true + "integrity": "sha512-4pXwmBplsCPv8FOY1WRakF970TjNGnGnfbOnLqjlYvMiF1SR3yOHyxMR/YCXpPTOspNF5gwudqktIP4VsWkvBg==" }, "fastq": { "version": "1.13.0", @@ -24063,6 +24585,12 @@ "verror": "1.10.0" } }, + "just-extend": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "dev": true + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -24349,6 +24877,12 @@ "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", "dev": true }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "dev": true + }, "lodash.ismatch": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", @@ -24801,7 +25335,6 @@ "version": "0.38.3", "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.3.tgz", "integrity": "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==", - "dev": true, "requires": { "obliterator": "^1.6.1" } @@ -24869,6 +25402,50 @@ "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", "dev": true }, + "nise": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.2.tgz", + "integrity": "sha512-+gQjFi8v+tkfCuSCxfURHLhRhniE/+IaYbIphxAN2JRR9SHKhY8hgXpaXiYfHdw+gcGe4buxgbprBQFab9FkhA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^2.0.0", + "@sinonjs/fake-timers": "^7.0.4", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + }, + "dependencies": { + "@sinonjs/commons": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz", + "integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + }, + "dependencies": { + "@sinonjs/commons": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.5.tgz", + "integrity": "sha512-rTpCA0wG1wUxglBSFdMMY0oTrKYvgf4fNgv/sXbfCVAdf+FnPBdKJR/7XbpTCwbCrvCbdPYnlWaUUYz4V2fPDA==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + } + } + } + } + }, "node-fetch": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", @@ -25287,8 +25864,7 @@ "obliterator": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-1.6.1.tgz", - "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==", - "dev": true + "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==" }, "once": { "version": "1.4.0", @@ -25610,6 +26186,23 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true + } + } + }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -26460,6 +27053,31 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "sinon": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.2.tgz", + "integrity": "sha512-59237HChms4kg7/sXhiRcUzdSkKuydDeTiamT/jesUVHshBgL8XAmhgFo0GfK6RruMDM/iRSij1EybmMog9cJw==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.8.3", + "@sinonjs/fake-timers": "^7.1.2", + "@sinonjs/samsam": "^6.0.2", + "diff": "^5.0.0", + "nise": "^5.1.0", + "supports-color": "^7.2.0" + }, + "dependencies": { + "@sinonjs/fake-timers": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz", + "integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + } + } + }, "sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -27101,8 +27719,7 @@ "tslib": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" }, "tsutils": { "version": "3.21.0", @@ -27336,8 +27953,7 @@ "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, "v8-compile-cache": { "version": "2.3.0", diff --git a/package.json b/package.json index c077b3c592..814fb8578d 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ "packages/commons", "packages/logger", "packages/metrics", - "packages/tracer" + "packages/tracer", + "packages/idempotency" ], "scripts": { "init-environment": "husky install", @@ -83,4 +84,4 @@ "dependencies": { "hosted-git-info": "^5.0.0" } -} +} \ No newline at end of file diff --git a/packages/idempotency/package.json b/packages/idempotency/package.json index 23d75bafb6..8ea2117115 100644 --- a/packages/idempotency/package.json +++ b/packages/idempotency/package.json @@ -13,18 +13,18 @@ "commit": "commit", "test": "npm run test:unit", "test:unit": "jest --group=unit --detectOpenHandles --coverage --verbose", - "test:e2e:nodejs12x": "RUNTIME=nodejs12x jest --group=e2e", - "test:e2e:nodejs14x": "RUNTIME=nodejs14x jest --group=e2e", - "test:e2e:nodejs16x": "RUNTIME=nodejs16x jest --group=e2e", - "test:e2e": "jest --group=e2e", + "test:e2e:nodejs12x": "echo \"Not implemented\"", + "test:e2e:nodejs14x": "echo \"Not implemented\"", + "test:e2e:nodejs16x": "echo \"Not implemented\"", + "test:e2e": "echo \"Not implemented\"", "watch": "jest --watch --group=unit", "build": "tsc", "lint": "eslint --ext .ts --no-error-on-unmatched-pattern src tests", "lint-fix": "eslint --fix --ext .ts --no-error-on-unmatched-pattern src tests", "package": "mkdir -p dist/ && npm pack && mv *.tgz dist/", - "package-bundle": "../../package-bundler.sh logger-bundle ./dist", + "package-bundle": "../../package-bundler.sh idempotency-bundle ./dist", "prepare": "npm run build", - "postversion": "git push --tags" + "postversion": "echo \"Not implemented\"" }, "homepage": "https://github.com/awslabs/aws-lambda-powertools-typescript/tree/master/packages/idempotency#readme", "license": "MIT", @@ -42,7 +42,7 @@ "url": "https://github.com/awslabs/aws-lambda-powertools-typescript/issues" }, "dependencies": { - "@aws-lambda-powertools/commons": "^1.2.1", + "@aws-lambda-powertools/commons": "^1.4.1", "@aws-sdk/lib-dynamodb": "^3.170.0" }, "keywords": [ @@ -56,4 +56,4 @@ "aws-sdk-client-mock": "^2.0.0", "aws-sdk-client-mock-jest": "^2.0.0" } -} +} \ No newline at end of file From 5da390e8732521718dc75f6962c41b9e0481c364 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Fri, 11 Nov 2022 19:28:38 +0100 Subject: [PATCH 02/11] ci: add idempotency to ci checks on PRs --- .../workflows/reusable-run-linting-check-and-unit-tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/reusable-run-linting-check-and-unit-tests.yml b/.github/workflows/reusable-run-linting-check-and-unit-tests.yml index 991260cb76..0269784106 100644 --- a/.github/workflows/reusable-run-linting-check-and-unit-tests.yml +++ b/.github/workflows/reusable-run-linting-check-and-unit-tests.yml @@ -42,11 +42,11 @@ jobs: if: steps.cache-node-modules.outputs.cache-hit == 'true' run: | npm run build -w packages/commons - npm run build -w packages/logger & npm run build -w packages/tracer & npm run build -w packages/metrics + npm run build -w packages/logger & npm run build -w packages/tracer & npm run build -w packages/metrics & npm run build -w packages/idempotency - name: Run linting - run: npm run lint -w packages/commons -w packages/logger -w packages/tracer -w packages/metrics + run: npm run lint -w packages/commons -w packages/logger -w packages/tracer -w packages/metrics -w packages/idempotency - name: Run unit tests - run: npm t -w packages/commons -w packages/logger -w packages/tracer -w packages/metrics + run: npm t -w packages/commons -w packages/logger -w packages/tracer -w packages/metrics -w packages/idempotency check-examples: runs-on: ubuntu-latest env: From 2359f659c8a14d7707a538c87b762217142c16f4 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Fri, 11 Nov 2022 19:29:42 +0100 Subject: [PATCH 03/11] refactor: minor styling changes to folder structure, exports, types --- .../src/EnvironmentVariablesService.ts | 25 ------------- .../src/config/ConfigServiceInterface.ts | 13 +++++++ .../src/config/EnvironmentVariablesService.ts | 36 +++++++++++++++++++ packages/idempotency/src/config/index.ts | 1 + .../idempotency/src/makeFunctionIdempotent.ts | 7 ++-- .../persistence/DynamoDbPersistenceLayer.ts | 5 +-- .../src/persistence/PersistenceLayer.ts | 27 +++++++++----- .../persistence/PersistenceLayerInterface.ts | 1 - .../DynamoPersistenceConstructorOptions.ts | 2 +- .../src/{ => types}/IdempotencyOptions.ts | 2 +- .../idempotency/src/types/PersistenceLayer.ts | 7 ++++ packages/idempotency/src/types/index.ts | 3 +- 12 files changed, 86 insertions(+), 43 deletions(-) delete mode 100644 packages/idempotency/src/EnvironmentVariablesService.ts create mode 100644 packages/idempotency/src/config/ConfigServiceInterface.ts create mode 100644 packages/idempotency/src/config/EnvironmentVariablesService.ts create mode 100644 packages/idempotency/src/config/index.ts rename packages/idempotency/src/{ => types}/IdempotencyOptions.ts (65%) create mode 100644 packages/idempotency/src/types/PersistenceLayer.ts diff --git a/packages/idempotency/src/EnvironmentVariablesService.ts b/packages/idempotency/src/EnvironmentVariablesService.ts deleted file mode 100644 index 4d9892e307..0000000000 --- a/packages/idempotency/src/EnvironmentVariablesService.ts +++ /dev/null @@ -1,25 +0,0 @@ -class EnvironmentVariablesService { - private lambdaFunctionNameVariable = 'AWS_LAMBDA_FUNCTION_NAME'; - - /** - * retrieve the value of an environment variable - * - * @param name the name of the environment variable - * @returns the value of the environment variable - */ - public get(name: string): string { - return process.env[name]?.trim() || ''; - } - /** - * retrieve the name of the Lambda function - * - * @returns the Lambda function name - */ - public getLambdaFunctionName(): string{ - return this.get(this.lambdaFunctionNameVariable); - } -} - -export { - EnvironmentVariablesService -}; \ No newline at end of file diff --git a/packages/idempotency/src/config/ConfigServiceInterface.ts b/packages/idempotency/src/config/ConfigServiceInterface.ts new file mode 100644 index 0000000000..f56dbc0d11 --- /dev/null +++ b/packages/idempotency/src/config/ConfigServiceInterface.ts @@ -0,0 +1,13 @@ +interface ConfigServiceInterface { + + get(name: string): string + + getServiceName(): string + + getFunctionName(): string + +} + +export { + ConfigServiceInterface +}; \ No newline at end of file diff --git a/packages/idempotency/src/config/EnvironmentVariablesService.ts b/packages/idempotency/src/config/EnvironmentVariablesService.ts new file mode 100644 index 0000000000..333faaca38 --- /dev/null +++ b/packages/idempotency/src/config/EnvironmentVariablesService.ts @@ -0,0 +1,36 @@ +import { ConfigServiceInterface } from './ConfigServiceInterface'; +import { EnvironmentVariablesService as CommonEnvironmentVariablesService } from '@aws-lambda-powertools/commons'; + +/** + * Class EnvironmentVariablesService + * + * This class is used to return environment variables that are available in the runtime of + * the current Lambda invocation. + * These variables can be a mix of runtime environment variables set by AWS and + * variables that can be set by the developer additionally. + * + * @class + * @extends {CommonEnvironmentVariablesService} + * @implements {ConfigServiceInterface} + * @see https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime + * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/#environment-variables + */ +class EnvironmentVariablesService extends CommonEnvironmentVariablesService implements ConfigServiceInterface { + + // Reserved environment variables + private functionNameVariable = 'AWS_LAMBDA_FUNCTION_NAME'; + + /** + * It returns the value of the AWS_LAMBDA_FUNCTION_NAME environment variable. + * + * @returns {string} + */ + public getFunctionName(): string { + return this.get(this.functionNameVariable); + } + +} + +export { + EnvironmentVariablesService +}; \ No newline at end of file diff --git a/packages/idempotency/src/config/index.ts b/packages/idempotency/src/config/index.ts new file mode 100644 index 0000000000..b55646be54 --- /dev/null +++ b/packages/idempotency/src/config/index.ts @@ -0,0 +1 @@ +export * from './EnvironmentVariablesService'; \ No newline at end of file diff --git a/packages/idempotency/src/makeFunctionIdempotent.ts b/packages/idempotency/src/makeFunctionIdempotent.ts index dc851396d6..40b6e52acf 100644 --- a/packages/idempotency/src/makeFunctionIdempotent.ts +++ b/packages/idempotency/src/makeFunctionIdempotent.ts @@ -1,10 +1,11 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { AnyFunction } from './types/AnyFunction'; -import { IdempotencyOptions } from './IdempotencyOptions'; +import type { AnyFunction } from './types/AnyFunction'; +import type { IdempotencyOptions } from './types/IdempotencyOptions'; const makeFunctionIdempotent = ( fn: AnyFunction, _options: IdempotencyOptions + // TODO: revisit this with a more specific type if possible + /* eslint-disable @typescript-eslint/no-explicit-any */ ): (...args: Array) => Promise => (...args) => fn(...args); export { makeFunctionIdempotent }; diff --git a/packages/idempotency/src/persistence/DynamoDbPersistenceLayer.ts b/packages/idempotency/src/persistence/DynamoDbPersistenceLayer.ts index 97cc752533..a0b9fe775e 100644 --- a/packages/idempotency/src/persistence/DynamoDbPersistenceLayer.ts +++ b/packages/idempotency/src/persistence/DynamoDbPersistenceLayer.ts @@ -1,5 +1,6 @@ import { DynamoDB, DynamoDBServiceException } from '@aws-sdk/client-dynamodb'; -import { DynamoDBDocument, GetCommandOutput } from '@aws-sdk/lib-dynamodb'; +import { DynamoDBDocument } from '@aws-sdk/lib-dynamodb'; +import type { GetCommandOutput } from '@aws-sdk/lib-dynamodb'; import { DynamoPersistenceConstructorOptions } from '../types/DynamoPersistenceConstructorOptions'; import { IdempotencyItemAlreadyExistsError, IdempotencyItemNotFoundError } from '../Exceptions'; import { IdempotencyRecordStatus } from '../types/IdempotencyRecordStatus'; @@ -23,7 +24,7 @@ class DynamoDBPersistenceLayer extends PersistenceLayer { this.statusAttr = constructorOptions.statusAttr ?? 'status'; this.expiryAttr = constructorOptions.expiryAttr ?? 'expiration'; this.inProgressExpiryAttr = constructorOptions.inProgressExpiryAttr ?? 'in_progress_expiry_attr'; - this.dataAttr = constructorOptions.data_attr ?? 'data'; + this.dataAttr = constructorOptions.dataAttr ?? 'data'; } protected async _deleteRecord(record: IdempotencyRecord): Promise { diff --git a/packages/idempotency/src/persistence/PersistenceLayer.ts b/packages/idempotency/src/persistence/PersistenceLayer.ts index d64c3d1546..0974cd91f5 100644 --- a/packages/idempotency/src/persistence/PersistenceLayer.ts +++ b/packages/idempotency/src/persistence/PersistenceLayer.ts @@ -1,6 +1,7 @@ import { BinaryToTextEncoding, createHash, Hash } from 'crypto'; import { IdempotencyRecordStatus } from '../types/IdempotencyRecordStatus'; -import { EnvironmentVariablesService } from '../EnvironmentVariablesService'; +import type { PersistenceLayerConfigureOptions } from '../types/PersistenceLayer'; +import { EnvironmentVariablesService } from '../config'; import { IdempotencyRecord } from './IdempotencyRecord'; import { PersistenceLayerInterface } from './PersistenceLayerInterface'; @@ -10,22 +11,30 @@ abstract class PersistenceLayer implements PersistenceLayerInterface { private envVarsService!: EnvironmentVariablesService; private expiresAfterSeconds: number; - - private functionName: string = ''; - + private hashDigest: BinaryToTextEncoding; - + private hashFunction: string; + + private idempotencyKeyPrefix: string; public constructor() { this.setEnvVarsService(); this.expiresAfterSeconds = 60 * 60; //one hour is the default expiration this.hashFunction = 'md5'; this.hashDigest = 'base64'; - + this.idempotencyKeyPrefix = this.getEnvVarsService().getFunctionName(); + } - public configure(functionName: string = ''): void { - this.functionName = this.getEnvVarsService().getLambdaFunctionName() + '.' + functionName; + + /** + * Configures the persistence layer by passing the name of the idempotent function. This will be used + * in the prefix of the idempotency key + * + * @param {PersistenceLayerConfigureOptions} options - configuration object for the persistence layer + */ + public configure(options?: PersistenceLayerConfigureOptions): void { + if (options?.functionName && options.functionName.trim() !== '') this.idempotencyKeyPrefix = `${this.idempotencyKeyPrefix}.${options.functionName}`; } /** @@ -136,7 +145,7 @@ abstract class PersistenceLayer implements PersistenceLayerInterface { console.warn('No data found for idempotency key'); } - return this.functionName + '#' + this.generateHash(JSON.stringify(data)); + return `${this.idempotencyKeyPrefix}#${this.generateHash(JSON.stringify(data))}`; } /** diff --git a/packages/idempotency/src/persistence/PersistenceLayerInterface.ts b/packages/idempotency/src/persistence/PersistenceLayerInterface.ts index e6bce97fde..65bcfae3dc 100644 --- a/packages/idempotency/src/persistence/PersistenceLayerInterface.ts +++ b/packages/idempotency/src/persistence/PersistenceLayerInterface.ts @@ -1,7 +1,6 @@ import { IdempotencyRecord } from './IdempotencyRecord'; interface PersistenceLayerInterface { - configure(functionName: string): void saveInProgress(data: unknown): Promise saveSuccess(data: unknown, result: unknown): Promise deleteRecord(data: unknown): Promise diff --git a/packages/idempotency/src/types/DynamoPersistenceConstructorOptions.ts b/packages/idempotency/src/types/DynamoPersistenceConstructorOptions.ts index c2308b362e..8ca7f7d4f3 100644 --- a/packages/idempotency/src/types/DynamoPersistenceConstructorOptions.ts +++ b/packages/idempotency/src/types/DynamoPersistenceConstructorOptions.ts @@ -4,7 +4,7 @@ type DynamoPersistenceConstructorOptions = { statusAttr?: string expiryAttr?: string inProgressExpiryAttr?: string - data_attr?: string + dataAttr?: string }; export { diff --git a/packages/idempotency/src/IdempotencyOptions.ts b/packages/idempotency/src/types/IdempotencyOptions.ts similarity index 65% rename from packages/idempotency/src/IdempotencyOptions.ts rename to packages/idempotency/src/types/IdempotencyOptions.ts index 53893cfe42..f7b445e65f 100644 --- a/packages/idempotency/src/IdempotencyOptions.ts +++ b/packages/idempotency/src/types/IdempotencyOptions.ts @@ -1,4 +1,4 @@ -import { PersistenceLayer } from './persistence/PersistenceLayer'; +import { PersistenceLayer } from '../persistence/PersistenceLayer'; type IdempotencyOptions = { dataKeywordArgument: string diff --git a/packages/idempotency/src/types/PersistenceLayer.ts b/packages/idempotency/src/types/PersistenceLayer.ts new file mode 100644 index 0000000000..3654648846 --- /dev/null +++ b/packages/idempotency/src/types/PersistenceLayer.ts @@ -0,0 +1,7 @@ +type PersistenceLayerConfigureOptions = { + functionName?: string +}; + +export { + PersistenceLayerConfigureOptions +}; \ No newline at end of file diff --git a/packages/idempotency/src/types/index.ts b/packages/idempotency/src/types/index.ts index 850ccbd19c..307c6bc093 100644 --- a/packages/idempotency/src/types/index.ts +++ b/packages/idempotency/src/types/index.ts @@ -1,2 +1,3 @@ export * from './AnyFunction'; -export * from './IdempotencyRecordStatus'; \ No newline at end of file +export * from './IdempotencyRecordStatus'; +export * from './PersistenceLayer'; \ No newline at end of file From bcc35b8811dc6fc7654b3b25edbcb169e1370998 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Fri, 11 Nov 2022 19:30:35 +0100 Subject: [PATCH 04/11] test: unit tests style + added missing --- .../helpers/populateEnvironmentVariables.ts | 7 +- .../unit/EnvironmentVariableService.test.ts | 34 --- .../config/EnvironmentVariableService.test.ts | 50 ++++ .../DynamoDbPersistenceLayer.test.ts | 209 +++++++++------- .../persistence/IdempotencyRecord.test.ts | 7 +- .../unit/persistence/PersistenceLayer.test.ts | 229 +++++++++++------- 6 files changed, 318 insertions(+), 218 deletions(-) delete mode 100644 packages/idempotency/tests/unit/EnvironmentVariableService.test.ts create mode 100644 packages/idempotency/tests/unit/config/EnvironmentVariableService.test.ts diff --git a/packages/idempotency/tests/helpers/populateEnvironmentVariables.ts b/packages/idempotency/tests/helpers/populateEnvironmentVariables.ts index 42b8feeb63..d38651b714 100644 --- a/packages/idempotency/tests/helpers/populateEnvironmentVariables.ts +++ b/packages/idempotency/tests/helpers/populateEnvironmentVariables.ts @@ -1,2 +1,7 @@ // Reserved variables -process.env.AWS_REGION = 'us-east-1'; +process.env._X_AMZN_TRACE_ID = '1-abcdef12-3456abcdef123456abcdef12'; +process.env.AWS_LAMBDA_FUNCTION_NAME = 'my-lambda-function'; +process.env.AWS_EXECUTION_ENV = 'nodejs16.x'; +process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '128'; +process.env.AWS_REGION = 'eu-west-1'; +process.env._HANDLER = 'index.handler'; \ No newline at end of file diff --git a/packages/idempotency/tests/unit/EnvironmentVariableService.test.ts b/packages/idempotency/tests/unit/EnvironmentVariableService.test.ts deleted file mode 100644 index 2480c328cb..0000000000 --- a/packages/idempotency/tests/unit/EnvironmentVariableService.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Test EnvironmentVariableService class - * - * @group unit/idempotency/all - */ -import { EnvironmentVariablesService } from '../../src/EnvironmentVariablesService'; - -describe('Class: EnvironmentVariableService', ()=> { - describe('Method: getLambdaFunctionName', ()=> { - beforeEach(() => { - process.env.AWS_LAMBDA_FUNCTION_NAME = 'testFunction'; - }); - - afterEach(()=> { - delete process.env.AWS_LAMBDA_FUNCTION_NAME; - }); - - test('When called, it gets the Lambda function name from the environment variable', ()=> { - const expectedName = process.env.AWS_LAMBDA_FUNCTION_NAME; - - const lambdaName = new EnvironmentVariablesService().getLambdaFunctionName(); - - expect(lambdaName).toEqual(expectedName); - }); - - test('When called without the environment variable set, it returns an empty string', ()=> { - delete process.env.AWS_LAMBDA_FUNCTION_NAME; - - const lambdaName = new EnvironmentVariablesService().getLambdaFunctionName(); - - expect(lambdaName).toEqual(''); - }); - }); -}); \ No newline at end of file diff --git a/packages/idempotency/tests/unit/config/EnvironmentVariableService.test.ts b/packages/idempotency/tests/unit/config/EnvironmentVariableService.test.ts new file mode 100644 index 0000000000..f4e44333e9 --- /dev/null +++ b/packages/idempotency/tests/unit/config/EnvironmentVariableService.test.ts @@ -0,0 +1,50 @@ +/** + * Test EnvironmentVariableService class + * + * @group unit/idempotency/all + */ +import { EnvironmentVariablesService } from '../../../src/config'; + +describe('Class: EnvironmentVariableService', () => { + + const ENVIRONMENT_VARIABLES = process.env; + + beforeEach(() => { + jest.resetModules(); + process.env = { ...ENVIRONMENT_VARIABLES }; + }); + + afterEach(() => { + process.env = ENVIRONMENT_VARIABLES; + }); + + describe('Method: getFunctionName', () => { + + test('When called, it gets the Lambda function name from the environment variable', () => { + + // Prepare + const expectedName = process.env.AWS_LAMBDA_FUNCTION_NAME; + + // Act + const lambdaName = new EnvironmentVariablesService().getFunctionName(); + + // Assess + expect(lambdaName).toEqual(expectedName); + + }); + + test('When called without the environment variable set, it returns an empty string', () => { + + // Prepare + delete process.env.AWS_LAMBDA_FUNCTION_NAME; + + // Act + const lambdaName = new EnvironmentVariablesService().getFunctionName(); + + // Assess + expect(lambdaName).toEqual(''); + + }); + + }); +}); \ No newline at end of file diff --git a/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts b/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts index 8ca16818dd..44dbfbeba4 100644 --- a/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts +++ b/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts @@ -1,19 +1,24 @@ +/** + * Test DynamoDBPersistenceLayer class + * + * @group unit/idempotency/all + */ import { DeleteCommand, DynamoDBDocument, GetCommand, PutCommand, UpdateCommand } from '@aws-sdk/lib-dynamodb'; import { mockClient } from 'aws-sdk-client-mock'; import 'aws-sdk-client-mock-jest'; import { IdempotencyItemAlreadyExistsError, IdempotencyItemNotFoundError } from '../../../src/Exceptions'; import { DynamoDBPersistenceLayer } from '../../../src/persistence/DynamoDbPersistenceLayer'; import { IdempotencyRecord } from '../../../src/persistence/IdempotencyRecord'; +import { DynamoPersistenceConstructorOptions } from '../../../src/types/DynamoPersistenceConstructorOptions'; import { IdempotencyRecordStatus } from '../../../src/types/IdempotencyRecordStatus'; -/** - * Test DynamoDBPersistenceLayer class - * - * @group unit/idempotency/all - */ +describe('Class: DynamoDBPersistenceLayer', () => { + + const dummyTableName = 'someTable'; + const dummyKey = 'someKey'; + + class TestDynamoDBPersistenceLayer extends DynamoDBPersistenceLayer { -describe('Class: DynamoDbPersistenceLayer', () => { - class TestDynamoPersistenceLayer extends DynamoDBPersistenceLayer { public _deleteRecord(record: IdempotencyRecord): Promise { return super._deleteRecord(record); } @@ -29,13 +34,61 @@ describe('Class: DynamoDbPersistenceLayer', () => { public _updateRecord(record: IdempotencyRecord): Promise { return super._updateRecord(record); } + } beforeEach(() => { jest.clearAllMocks(); }); + describe('Method: constructor', () => { + + test('when instantiated with minimum options it creates an instance with default values', () => { + + // Prepare + const persistenceLayer = new TestDynamoDBPersistenceLayer({ tableName: dummyTableName }); + + // Act / Assess + expect(persistenceLayer).toEqual(expect.objectContaining({ + tableName: dummyTableName, + keyAttr: 'id', + statusAttr: 'status', + expiryAttr: 'expiration', + inProgressExpiryAttr: 'in_progress_expiry_attr', + dataAttr: 'data' + })); + + }); + + test('when instantiated with specific options it creates an instance with correct values', () => { + + // Prepare + const testDynamoDBPersistenceLayerOptions: DynamoPersistenceConstructorOptions = { + tableName: dummyTableName, + keyAttr: dummyKey, + statusAttr: 'someStatusAttr', + expiryAttr: 'someExpiryAttr', + inProgressExpiryAttr: 'someInProgressExpiryAttr', + dataAttr: 'someDataAttr' + }; + const persistenceLayer = new TestDynamoDBPersistenceLayer(testDynamoDBPersistenceLayerOptions); + + // Act / Assess + expect(persistenceLayer).toEqual(expect.objectContaining({ + tableName: dummyTableName, + keyAttr: dummyKey, + statusAttr: testDynamoDBPersistenceLayerOptions.statusAttr, + expiryAttr: testDynamoDBPersistenceLayerOptions.expiryAttr, + inProgressExpiryAttr: testDynamoDBPersistenceLayerOptions.inProgressExpiryAttr, + dataAttr: testDynamoDBPersistenceLayerOptions.dataAttr + })); + + }); + + }); + describe('Method: _putRecord', () => { + const currentDateInMilliseconds = 1000; const currentDateInSeconds = 1; @@ -43,17 +96,15 @@ describe('Class: DynamoDbPersistenceLayer', () => { jest.spyOn(Date, 'now').mockReturnValue(currentDateInMilliseconds); }); - test('when called with a record that meets conditions, it puts record in dynamo table', async () => { - // Prepare - const tableName = 'tableName'; - const persistenceLayer = new TestDynamoPersistenceLayer({ tableName }); + test('when called with a record that meets conditions, it puts record in DynamoDB table', async () => { - const key = 'key'; + // Prepare + const persistenceLayer = new TestDynamoDBPersistenceLayer({ tableName: dummyTableName }); const status = IdempotencyRecordStatus.EXPIRED; const expiryTimestamp = 0; const inProgressExpiryTimestamp = 0; const record = new IdempotencyRecord({ - idempotencyKey: key, + idempotencyKey: dummyKey, status, expiryTimestamp, inProgressExpiryTimestamp @@ -65,104 +116,84 @@ describe('Class: DynamoDbPersistenceLayer', () => { // Assess expect(dynamoClient).toReceiveCommandWith(PutCommand, { - TableName: tableName, - Item: { 'id': key, 'expiration': expiryTimestamp, status: status }, + TableName: dummyTableName, + Item: { 'id': dummyKey, 'expiration': expiryTimestamp, status: status }, ExpressionAttributeNames: { '#id': 'id', '#expiry': 'expiration', '#status': 'status' }, ExpressionAttributeValues: { ':now': currentDateInSeconds, ':inprogress': IdempotencyRecordStatus.INPROGRESS }, ConditionExpression: 'attribute_not_exists(#id) OR #expiry < :now OR NOT #status = :inprogress' }); + }); test('when called with a record that fails any condition, it throws IdempotencyItemAlreadyExistsError', async () => { + // Prepare - const tableName = 'tableName'; - const persistenceLayer = new TestDynamoPersistenceLayer({ tableName }); - - const key = 'key'; + const persistenceLayer = new TestDynamoDBPersistenceLayer({ tableName: dummyTableName }); const status = IdempotencyRecordStatus.EXPIRED; const expiryTimestamp = 0; const inProgressExpiryTimestamp = 0; const record = new IdempotencyRecord({ - idempotencyKey: key, + idempotencyKey: dummyKey, status, expiryTimestamp, inProgressExpiryTimestamp }); - const dynamoClient = mockClient(DynamoDBDocument).on(PutCommand).rejects({ name: 'ConditionalCheckFailedException' }); - // Act - let error: unknown; - try { - await persistenceLayer._putRecord(record); - } catch (e){ - error = e; - } - - // Assess + // Act / Assess + await expect(persistenceLayer._putRecord(record)).rejects.toThrowError(IdempotencyItemAlreadyExistsError); expect(dynamoClient).toReceiveCommandWith(PutCommand, { - TableName: tableName, - Item: { 'id': key, 'expiration': expiryTimestamp, status: status }, + TableName: dummyTableName, + Item: { 'id': dummyKey, 'expiration': expiryTimestamp, status: status }, ExpressionAttributeNames: { '#id': 'id', '#expiry': 'expiration', '#status': 'status' }, ExpressionAttributeValues: { ':now': currentDateInSeconds, ':inprogress': IdempotencyRecordStatus.INPROGRESS }, ConditionExpression: 'attribute_not_exists(#id) OR #expiry < :now OR NOT #status = :inprogress' }); - expect(error).toBeInstanceOf(IdempotencyItemAlreadyExistsError); + }); test('when encountering an unknown error, it throws the causing error', async () => { - // Prepare - const tableName = 'tableName'; - const persistenceLayer = new TestDynamoPersistenceLayer({ tableName }); - const key = 'key'; + // Prepare + const persistenceLayer = new TestDynamoDBPersistenceLayer({ tableName: dummyTableName }); const status = IdempotencyRecordStatus.EXPIRED; const expiryTimestamp = 0; const inProgressExpiryTimestamp = 0; const record = new IdempotencyRecord({ - idempotencyKey: key, + idempotencyKey: dummyKey, status, expiryTimestamp, inProgressExpiryTimestamp }); - const dynamoClient = mockClient(DynamoDBDocument).on(PutCommand).rejects(new Error()); - // Act - let error: unknown; - try { - await persistenceLayer._putRecord(record); - } catch (e){ - error = e; - } - - // Assess + // Act / Assess + await expect(persistenceLayer._putRecord(record)).rejects.toThrow(); expect(dynamoClient).toReceiveCommandWith(PutCommand, { - TableName: tableName, - Item: { 'id': key, 'expiration': expiryTimestamp, status: status }, + TableName: dummyTableName, + Item: { 'id': dummyKey, 'expiration': expiryTimestamp, status: status }, ExpressionAttributeNames: { '#id': 'id', '#expiry': 'expiration', '#status': 'status' }, ExpressionAttributeValues: { ':now': currentDateInSeconds, ':inprogress': IdempotencyRecordStatus.INPROGRESS }, ConditionExpression: 'attribute_not_exists(#id) OR #expiry < :now OR NOT #status = :inprogress' }); - expect(error).toBe(error); + }); + }); describe('Method: _getRecord', () => { - test('when called with a record whose key exists, it gets the correct record', async () => { - // Prepare - const tableName = 'tableName'; - const persistenceLayer = new TestDynamoPersistenceLayer({ tableName }); - const key = 'key'; + test('when called with a record whose key exists, it gets the correct record', async () => { + // Prepare + const persistenceLayer = new TestDynamoDBPersistenceLayer({ tableName: dummyTableName }); const status = IdempotencyRecordStatus.INPROGRESS; const expiryTimestamp = 10; const inProgressExpiryTimestamp = 10; const responseData = {}; const dynamoClient = mockClient(DynamoDBDocument).on(GetCommand).resolves({ Item: { - id: key, + id: dummyKey, status, 'expiration': expiryTimestamp, 'in_progress_expiry_attr': inProgressExpiryTimestamp, @@ -172,65 +203,55 @@ describe('Class: DynamoDbPersistenceLayer', () => { jest.spyOn(Date, 'now').mockReturnValue(0); // Act - const record: IdempotencyRecord = await persistenceLayer._getRecord(key); + const record: IdempotencyRecord = await persistenceLayer._getRecord(dummyKey); // Assess expect(dynamoClient).toReceiveCommandWith(GetCommand, { - TableName: tableName, + TableName: dummyTableName, Key: { - id: key + id: dummyKey }, ConsistentRead: true }); expect(record.getStatus()).toEqual(IdempotencyRecordStatus.INPROGRESS); - expect(record.idempotencyKey).toEqual(key); + expect(record.idempotencyKey).toEqual(dummyKey); expect(record.inProgressExpiryTimestamp).toEqual(inProgressExpiryTimestamp); expect(record.responseData).toEqual(responseData); expect(record.expiryTimestamp).toEqual(expiryTimestamp); }); test('when called with a record whose key does not exist, it throws IdempotencyItemNotFoundError', async () => { - // Prepare - const tableName = 'tableName'; - const persistenceLayer = new TestDynamoPersistenceLayer({ tableName }); - - const key = 'key'; + // Prepare + const persistenceLayer = new TestDynamoDBPersistenceLayer({ tableName: dummyTableName }); const dynamoClient = mockClient(DynamoDBDocument).on(GetCommand).resolves({ Item: undefined }); jest.spyOn(Date, 'now').mockReturnValue(0); - // Act - let error: unknown; - try { - await persistenceLayer._getRecord(key); - } catch (e){ - error = e; - } - - // Assess + // Act / Assess + await expect(persistenceLayer._getRecord(dummyKey)).rejects.toThrowError(IdempotencyItemNotFoundError); expect(dynamoClient).toReceiveCommandWith(GetCommand, { - TableName: tableName, + TableName: dummyTableName, Key: { - id: key + id: dummyKey }, ConsistentRead: true }); - expect(error).toBeInstanceOf(IdempotencyItemNotFoundError); + }); + }); describe('Method: _updateRecord', () => { + test('when called to update a record, it resolves successfully', async () => { - // Prepare - const tableName = 'tableName'; - const persistenceLayer = new TestDynamoPersistenceLayer({ tableName }); - const key = 'key'; + // Prepare + const persistenceLayer = new TestDynamoDBPersistenceLayer({ tableName: dummyTableName }); const status = IdempotencyRecordStatus.EXPIRED; const expiryTimestamp = 0; const inProgressExpiryTimestamp = 0; const record = new IdempotencyRecord({ - idempotencyKey: key, + idempotencyKey: dummyKey, status, expiryTimestamp, inProgressExpiryTimestamp @@ -242,27 +263,28 @@ describe('Class: DynamoDbPersistenceLayer', () => { // Assess expect(dynamoClient).toReceiveCommandWith(UpdateCommand, { - TableName: tableName, - Key: { id: key }, + TableName: dummyTableName, + Key: { id: dummyKey }, UpdateExpression: 'SET #status = :status, #expiry = :expiry', ExpressionAttributeNames: { '#status': 'status', '#expiry': 'expiration' }, ExpressionAttributeValues: { ':status': IdempotencyRecordStatus.EXPIRED,':expiry': expiryTimestamp }, }); + }); + }); describe('Method: _deleteRecord', () => { + test('when called with a valid record, record is deleted', async () => { - // Prepare - const tableName = 'tableName'; - const persistenceLayer = new TestDynamoPersistenceLayer({ tableName }); - const key = 'key'; + // Prepare + const persistenceLayer = new TestDynamoDBPersistenceLayer({ tableName: dummyTableName }); const status = IdempotencyRecordStatus.EXPIRED; const expiryTimestamp = 0; const inProgressExpiryTimestamp = 0; const record = new IdempotencyRecord({ - idempotencyKey: key, + idempotencyKey: dummyKey, status, expiryTimestamp, inProgressExpiryTimestamp @@ -274,9 +296,12 @@ describe('Class: DynamoDbPersistenceLayer', () => { // Assess expect(dynamoClient).toReceiveCommandWith(DeleteCommand, { - TableName: tableName, - Key: { id: key } + TableName: dummyTableName, + Key: { id: dummyKey } }); + }); + }); + }); \ No newline at end of file diff --git a/packages/idempotency/tests/unit/persistence/IdempotencyRecord.test.ts b/packages/idempotency/tests/unit/persistence/IdempotencyRecord.test.ts index 7f0c00db04..3d42ed2059 100644 --- a/packages/idempotency/tests/unit/persistence/IdempotencyRecord.test.ts +++ b/packages/idempotency/tests/unit/persistence/IdempotencyRecord.test.ts @@ -1,11 +1,12 @@ -import { IdempotencyInvalidStatusError } from '../../../src/Exceptions'; -import { IdempotencyRecord } from '../../../src/persistence/IdempotencyRecord'; -import { IdempotencyRecordStatus } from '../../../src/types/IdempotencyRecordStatus'; /** * Test IdempotencyRecord class * * @group unit/idempotency/all */ +import { IdempotencyInvalidStatusError } from '../../../src/Exceptions'; +import { IdempotencyRecord } from '../../../src/persistence/IdempotencyRecord'; +import { IdempotencyRecordStatus } from '../../../src/types/IdempotencyRecordStatus'; + const mockIdempotencyKey = '123'; const mockData = undefined; const mockInProgressExpiry = 123; diff --git a/packages/idempotency/tests/unit/persistence/PersistenceLayer.test.ts b/packages/idempotency/tests/unit/persistence/PersistenceLayer.test.ts index ee899c3342..5fe3c42cf5 100644 --- a/packages/idempotency/tests/unit/persistence/PersistenceLayer.test.ts +++ b/packages/idempotency/tests/unit/persistence/PersistenceLayer.test.ts @@ -4,7 +4,6 @@ * @group unit/idempotency/all */ import { createHash, Hash } from 'crypto'; -import { EnvironmentVariablesService } from '../../../src/EnvironmentVariablesService'; import { IdempotencyRecord, PersistenceLayer } from '../../../src/persistence'; import { IdempotencyRecordStatus } from '../../../src/types/IdempotencyRecordStatus'; @@ -16,7 +15,10 @@ const cryptoUpdateMock = jest.fn(); const cryptoDigestMock = jest.fn(); const mockDigest = 'hashDigest'; -describe('Class: Persistence Layer', ()=> { +describe('Class: PersistenceLayer', () => { + + const dummyData = 'someData'; + const idempotentFunctionName = 'foo'; const deleteRecord = jest.fn(); const getRecord = jest.fn(); @@ -34,102 +36,146 @@ describe('Class: Persistence Layer', ()=> { protected _updateRecord = updateRecord; } - describe('Method: saveInProgress', ()=> { - beforeEach(()=> { - putRecord.mockClear(); - (createHash as jest.MockedFunction).mockReturnValue( - { - update: cryptoUpdateMock, - digest: cryptoDigestMock.mockReturnValue(mockDigest) - } as unknown as Hash - ); + describe('Method: configure', () => { + + test('when called without options it maintains the default value for the key prefix', () => { + + // Prepare + const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); + persistenceLayer.configure(); + + expect(persistenceLayer).toEqual(expect.objectContaining({ + idempotencyKeyPrefix: process.env.AWS_LAMBDA_FUNCTION_NAME, + })); + }); - test('When called, it saves an IN_PROGRESS idempotency record via _putRecord()', async ()=> { - const data = 'someData'; + test('when called with an empty option object it maintains the default value for the key prefix', () => { + + // Prepare const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); + persistenceLayer.configure({}); - await persistenceLayer.saveInProgress(data); + expect(persistenceLayer).toEqual(expect.objectContaining({ + idempotencyKeyPrefix: process.env.AWS_LAMBDA_FUNCTION_NAME, + })); - const savedIdempotencyRecord: IdempotencyRecord = putRecord.mock.calls[0][0]; - expect(savedIdempotencyRecord.getStatus()).toBe(IdempotencyRecordStatus.INPROGRESS); }); - test('When called, it creates an idempotency key from the function name and a digest of the md5 hash of the data', async ()=> { - const data = 'someData'; - const lambdaFunctionName = 'LambdaName'; - jest.spyOn(EnvironmentVariablesService.prototype, 'getLambdaFunctionName').mockReturnValue(lambdaFunctionName); + test('when called with an empty string as functionName it maintains the default value for the key prefix', () => { - const functionName = 'functionName'; + // Prepare + const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); + persistenceLayer.configure({ functionName: '' }); - const expectedIdempotencyKey = lambdaFunctionName + '.' + functionName + '#' + mockDigest; + expect(persistenceLayer).toEqual(expect.objectContaining({ + idempotencyKeyPrefix: process.env.AWS_LAMBDA_FUNCTION_NAME, + })); + + }); + + test('when called with a valid functionName it concatenates the key prefix correctly', () => { + + // Prepare + const expectedIdempotencyKeyPrefix = `${process.env.AWS_LAMBDA_FUNCTION_NAME}.${idempotentFunctionName}`; const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); - persistenceLayer.configure(functionName); + persistenceLayer.configure({ functionName: idempotentFunctionName }); - await persistenceLayer.saveInProgress(data); + expect(persistenceLayer).toEqual(expect.objectContaining({ + idempotencyKeyPrefix: expectedIdempotencyKeyPrefix + })); - const savedIdempotencyRecord: IdempotencyRecord = putRecord.mock.calls[0][0]; + }); - expect(createHash).toHaveBeenCalledWith( - expect.stringMatching('md5'), - ); - expect(cryptoUpdateMock).toHaveBeenCalledWith(expect.stringMatching(data)); - expect(cryptoDigestMock).toHaveBeenCalledWith( - expect.stringMatching('base64') + }); + + describe('Method: saveInProgress', () => { + + beforeEach(() => { + putRecord.mockClear(); + (createHash as jest.MockedFunction).mockReturnValue( + { + update: cryptoUpdateMock, + digest: cryptoDigestMock.mockReturnValue(mockDigest) + } as unknown as Hash ); - expect(savedIdempotencyRecord.idempotencyKey).toEqual(expectedIdempotencyKey); + }); - test('When called without a function name, it creates an idempotency key from the Lambda name only and a digest of the md5 hash of the data', async ()=> { - const data = 'someData'; - const lambdaFunctionName = 'LambdaName'; - jest.spyOn(EnvironmentVariablesService.prototype, 'getLambdaFunctionName').mockReturnValue(lambdaFunctionName); + test('when called, it saves an IN_PROGRESS idempotency record via _putRecord()', async () => { - const expectedIdempotencyKey = lambdaFunctionName + '.' + '#' + mockDigest; + // Prepare const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); - persistenceLayer.configure(); - await persistenceLayer.saveInProgress(data); + // Act + await persistenceLayer.saveInProgress(dummyData); + // Assess const savedIdempotencyRecord: IdempotencyRecord = putRecord.mock.calls[0][0]; + expect(savedIdempotencyRecord.getStatus()).toBe(IdempotencyRecordStatus.INPROGRESS); + + }); + test('when called, it creates an idempotency key from the function name and a digest of the md5 hash of the data', async () => { + + // Prepare + const expectedIdempotencyKey = `${process.env.AWS_LAMBDA_FUNCTION_NAME}.${idempotentFunctionName}#${mockDigest}`; + const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); + persistenceLayer.configure({ functionName: idempotentFunctionName }); + + // Act + await persistenceLayer.saveInProgress(dummyData); + + // Assess + const savedIdempotencyRecord: IdempotencyRecord = putRecord.mock.calls[0][0]; expect(createHash).toHaveBeenCalledWith( expect.stringMatching('md5'), ); - expect(cryptoUpdateMock).toHaveBeenCalledWith(expect.stringMatching(data)); + expect(cryptoUpdateMock).toHaveBeenCalledWith(expect.stringMatching(dummyData)); expect(cryptoDigestMock).toHaveBeenCalledWith( expect.stringMatching('base64') ); expect(savedIdempotencyRecord.idempotencyKey).toEqual(expectedIdempotencyKey); + }); - test('When called, it sets the expiry timestamp to one hour in the future', async ()=> { + test('when called, it sets the expiry timestamp to one hour in the future', async () => { + + // Prepare const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); - const data = 'someData'; const currentMillisTime = 3000; const currentSeconds = currentMillisTime / 1000; const oneHourSeconds = 60 * 60; jest.spyOn(Date, 'now').mockReturnValue(currentMillisTime); - await persistenceLayer.saveInProgress(data); + // Act + await persistenceLayer.saveInProgress(dummyData); + // Assess const savedIdempotencyRecord: IdempotencyRecord = putRecord.mock.calls[0][0]; expect(savedIdempotencyRecord.expiryTimestamp).toEqual(currentSeconds + oneHourSeconds); }); - test('When called without data, it logs a warning', async ()=> { - const consoleSpy = jest.spyOn(console, 'warn'); + test('when called without data, it logs a warning', async () => { + + // Prepare + const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => ({})); const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); + // Act await persistenceLayer.saveInProgress(''); + + // Assess expect(consoleSpy).toHaveBeenCalled(); + }); }); - describe('Method: saveSuccess', ()=> { - beforeEach(()=> { + describe('Method: saveSuccess', () => { + + beforeEach(() => { updateRecord.mockClear(); (createHash as jest.MockedFunction).mockReturnValue( { @@ -139,55 +185,59 @@ describe('Class: Persistence Layer', ()=> { ); }); - test('When called, it updates the idempotency record status to COMPLETED', async () => { - const data = 'someData'; + test('when called, it updates the idempotency record status to COMPLETED', async () => { + + // Prepare const result = {}; const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); - await persistenceLayer.saveSuccess(data, result); + // Act + await persistenceLayer.saveSuccess(dummyData, result); + // Assess const savedIdempotencyRecord: IdempotencyRecord = updateRecord.mock.calls[0][0]; expect(savedIdempotencyRecord.getStatus()).toBe(IdempotencyRecordStatus.COMPLETED); }); - test('When called, it generates the idempotency key from the function name and a digest of the md5 hash of the data', async ()=> { - const data = 'someData'; - const result = {}; - const lambdaFunctionName = 'LambdaName'; - jest.spyOn(EnvironmentVariablesService.prototype, 'getLambdaFunctionName').mockReturnValue(lambdaFunctionName); - - const functionName = 'functionName'; + test('when called, it generates the idempotency key from the function name and a digest of the md5 hash of the data', async () => { - const expectedIdempotencyKey = lambdaFunctionName + '.' + functionName + '#' + mockDigest; + // Prepare + const result = {}; + const expectedIdempotencyKey = `${process.env.AWS_LAMBDA_FUNCTION_NAME}.${idempotentFunctionName}#${mockDigest}`; const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); - persistenceLayer.configure(functionName); + persistenceLayer.configure({ functionName: idempotentFunctionName }); - await persistenceLayer.saveSuccess(data, result); + // Act + await persistenceLayer.saveSuccess(dummyData, result); + // Assess const savedIdempotencyRecord: IdempotencyRecord = updateRecord.mock.calls[0][0]; - expect(createHash).toHaveBeenCalledWith( expect.stringMatching('md5'), ); - expect(cryptoUpdateMock).toHaveBeenCalledWith(expect.stringMatching(data)); + expect(cryptoUpdateMock).toHaveBeenCalledWith(expect.stringMatching(dummyData)); expect(cryptoDigestMock).toHaveBeenCalledWith( expect.stringMatching('base64') ); expect(savedIdempotencyRecord.idempotencyKey).toEqual(expectedIdempotencyKey); + }); - test('When called, it sets the expiry timestamp to one hour in the future', async ()=> { + test('when called, it sets the expiry timestamp to one hour in the future', async () => { + + // Prepare const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); - const data = 'someData'; const result = {}; const currentMillisTime = 3000; const currentSeconds = currentMillisTime / 1000; const oneHourSeconds = 60 * 60; jest.spyOn(Date, 'now').mockReturnValue(currentMillisTime); - await persistenceLayer.saveSuccess(data, result); + // Act + await persistenceLayer.saveSuccess(dummyData, result); + // Assess const savedIdempotencyRecord: IdempotencyRecord = updateRecord.mock.calls[0][0]; expect(savedIdempotencyRecord.expiryTimestamp).toEqual(currentSeconds + oneHourSeconds); @@ -195,8 +245,9 @@ describe('Class: Persistence Layer', ()=> { }); - describe('Method: getRecord', ()=> { - beforeEach(()=> { + describe('Method: getRecord', () => { + + beforeEach(() => { putRecord.mockClear(); (createHash as jest.MockedFunction).mockReturnValue( { @@ -205,24 +256,26 @@ describe('Class: Persistence Layer', ()=> { } as unknown as Hash ); }); - test('When called, it gets the record for the idempotency key for the data passed in', ()=> { - const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); - const data = 'someData'; - const lambdaFunctionName = 'LambdaName'; - jest.spyOn(EnvironmentVariablesService.prototype, 'getLambdaFunctionName').mockReturnValue(lambdaFunctionName); - const functionName = 'functionName'; - const expectedIdempotencyKey = lambdaFunctionName + '.' + functionName + '#' + mockDigest; - persistenceLayer.configure(functionName); + test('when called, it gets the record for the idempotency key for the data passed in', () => { - persistenceLayer.getRecord(data); + // Prepare + const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); + const expectedIdempotencyKey = `${process.env.AWS_LAMBDA_FUNCTION_NAME}.${idempotentFunctionName}#${mockDigest}`; + persistenceLayer.configure({ functionName: idempotentFunctionName }); + + // Act + persistenceLayer.getRecord(dummyData); + // Assess expect(getRecord).toHaveBeenCalledWith(expectedIdempotencyKey); + }); }); - describe('Method: deleteRecord', ()=> { - beforeEach(()=> { + describe('Method: deleteRecord', () => { + + beforeEach(() => { putRecord.mockClear(); (createHash as jest.MockedFunction).mockReturnValue( { @@ -232,20 +285,20 @@ describe('Class: Persistence Layer', ()=> { ); }); - test('When called, it deletes the record with the idempotency key for the data passed in', ()=> { - const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); - const data = 'someData'; - const lambdaFunctionName = 'LambdaName'; - jest.spyOn(EnvironmentVariablesService.prototype, 'getLambdaFunctionName').mockReturnValue(lambdaFunctionName); + test('when called, it deletes the record with the idempotency key for the data passed in', () => { - const functionName = 'functionName'; - const expectedIdempotencyKey = lambdaFunctionName + '.' + functionName + '#' + mockDigest; - persistenceLayer.configure(functionName); + // Prepare + const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); + const expectedIdempotencyKey = `${process.env.AWS_LAMBDA_FUNCTION_NAME}.${idempotentFunctionName}#${mockDigest}`; + persistenceLayer.configure({ functionName: idempotentFunctionName }); - persistenceLayer.deleteRecord(data); + // Act + persistenceLayer.deleteRecord(dummyData); + + // Assess const deletedIdempotencyRecord: IdempotencyRecord = deleteRecord.mock.calls[0][0]; - expect(deletedIdempotencyRecord.idempotencyKey).toEqual(expectedIdempotencyKey); + }); }); }); \ No newline at end of file From 542ec1713eb8f2f7a844a9a4cb04d38b2d9efe71 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Fri, 11 Nov 2022 19:31:11 +0100 Subject: [PATCH 05/11] chore: temporarily excluded makeFunctionIdempotent from coverage report --- packages/idempotency/jest.config.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/idempotency/jest.config.js b/packages/idempotency/jest.config.js index 8f1701110c..c33c7e13fc 100644 --- a/packages/idempotency/jest.config.js +++ b/packages/idempotency/jest.config.js @@ -1,7 +1,7 @@ module.exports = { displayName: { name: 'AWS Lambda Powertools utility: IDEMPOTENCY', - color: 'cyan', + color: 'blue', }, 'runner': 'groups', 'preset': 'ts-jest', @@ -25,6 +25,7 @@ module.exports = { 'coveragePathIgnorePatterns': [ '/node_modules/', '/types/', + 'src/makeFunctionIdempotent.ts', // TODO: remove this once makeFunctionIdempotent is implemented ], 'coverageThreshold': { 'global': { @@ -38,5 +39,8 @@ module.exports = { 'json-summary', 'text', 'lcov' + ], + 'setupFiles': [ + '/tests/helpers/populateEnvironmentVariables.ts' ] }; \ No newline at end of file From fd823833c227904b203980acf0da718fdf3576ef Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Fri, 11 Nov 2022 19:56:13 +0100 Subject: [PATCH 06/11] refactor: rename npx DynamoDbPersistenceLayer to DynamoDBPersistenceLayer --- packages/idempotency/src/persistence/index.ts | 2 +- .../tests/unit/persistence/DynamoDbPersistenceLayer.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/idempotency/src/persistence/index.ts b/packages/idempotency/src/persistence/index.ts index 7256fa4e7b..01dfd9be77 100644 --- a/packages/idempotency/src/persistence/index.ts +++ b/packages/idempotency/src/persistence/index.ts @@ -1,4 +1,4 @@ -export * from './DynamoDbPersistenceLayer'; +export * from './DynamoDBPersistenceLayer'; export * from './PersistenceLayer'; export * from './PersistenceLayerInterface'; export * from './IdempotencyRecord'; \ No newline at end of file diff --git a/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts b/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts index 44dbfbeba4..46d3b3e23d 100644 --- a/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts +++ b/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts @@ -7,7 +7,7 @@ import { DeleteCommand, DynamoDBDocument, GetCommand, PutCommand, UpdateCommand import { mockClient } from 'aws-sdk-client-mock'; import 'aws-sdk-client-mock-jest'; import { IdempotencyItemAlreadyExistsError, IdempotencyItemNotFoundError } from '../../../src/Exceptions'; -import { DynamoDBPersistenceLayer } from '../../../src/persistence/DynamoDbPersistenceLayer'; +import { DynamoDBPersistenceLayer } from '../../../src/persistence/DynamoDBPersistenceLayer'; import { IdempotencyRecord } from '../../../src/persistence/IdempotencyRecord'; import { DynamoPersistenceConstructorOptions } from '../../../src/types/DynamoPersistenceConstructorOptions'; import { IdempotencyRecordStatus } from '../../../src/types/IdempotencyRecordStatus'; From 2b53ed8bfef801480db7155839db2a4a21a2fe1f Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Fri, 11 Nov 2022 20:02:05 +0100 Subject: [PATCH 07/11] refactor: rename npx DynamoDbPersistenceLayer to DynamoDBPersistenceLayer --- .../DynamoDbPersistenceLayer.ts => DynamoDBPersistenceLayer.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/idempotency/src/{persistence/DynamoDbPersistenceLayer.ts => DynamoDBPersistenceLayer.ts} (100%) diff --git a/packages/idempotency/src/persistence/DynamoDbPersistenceLayer.ts b/packages/idempotency/src/DynamoDBPersistenceLayer.ts similarity index 100% rename from packages/idempotency/src/persistence/DynamoDbPersistenceLayer.ts rename to packages/idempotency/src/DynamoDBPersistenceLayer.ts From c91473110f94cba79ddc40cca47698c8955a562c Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Fri, 11 Nov 2022 20:08:54 +0100 Subject: [PATCH 08/11] refactor: rename npx DynamoDbPersistenceLayer to DynamoDBPersistenceLayer --- .../idempotency/src/{ => persistence}/DynamoDBPersistenceLayer.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/idempotency/src/{ => persistence}/DynamoDBPersistenceLayer.ts (100%) diff --git a/packages/idempotency/src/DynamoDBPersistenceLayer.ts b/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts similarity index 100% rename from packages/idempotency/src/DynamoDBPersistenceLayer.ts rename to packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts From 7c020872c22d6d45d7f401669665e9db805c51a2 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Fri, 11 Nov 2022 20:16:06 +0100 Subject: [PATCH 09/11] chore: revert changes to PersistenceLayerInterface --- .../idempotency/src/persistence/PersistenceLayerInterface.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/idempotency/src/persistence/PersistenceLayerInterface.ts b/packages/idempotency/src/persistence/PersistenceLayerInterface.ts index 65bcfae3dc..3eb5a9d0f0 100644 --- a/packages/idempotency/src/persistence/PersistenceLayerInterface.ts +++ b/packages/idempotency/src/persistence/PersistenceLayerInterface.ts @@ -1,6 +1,8 @@ import { IdempotencyRecord } from './IdempotencyRecord'; +import type { PersistenceLayerConfigureOptions } from '../types/PersistenceLayer'; interface PersistenceLayerInterface { + configure(options?: PersistenceLayerConfigureOptions): void saveInProgress(data: unknown): Promise saveSuccess(data: unknown, result: unknown): Promise deleteRecord(data: unknown): Promise From d64cd95b69e7dcf9497c7145cb1c46c95c9d7d55 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Mon, 14 Nov 2022 10:20:41 +0100 Subject: [PATCH 10/11] Trigger Build From d66731faa46fc552afb52ebbbfd8a950bd6785cc Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Tue, 15 Nov 2022 16:06:04 +0100 Subject: [PATCH 11/11] Update packages/idempotency/src/persistence/PersistenceLayer.ts Co-authored-by: ijemmy --- packages/idempotency/src/persistence/PersistenceLayer.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/idempotency/src/persistence/PersistenceLayer.ts b/packages/idempotency/src/persistence/PersistenceLayer.ts index 0974cd91f5..9325723312 100644 --- a/packages/idempotency/src/persistence/PersistenceLayer.ts +++ b/packages/idempotency/src/persistence/PersistenceLayer.ts @@ -34,7 +34,9 @@ abstract class PersistenceLayer implements PersistenceLayerInterface { * @param {PersistenceLayerConfigureOptions} options - configuration object for the persistence layer */ public configure(options?: PersistenceLayerConfigureOptions): void { - if (options?.functionName && options.functionName.trim() !== '') this.idempotencyKeyPrefix = `${this.idempotencyKeyPrefix}.${options.functionName}`; + if (options?.functionName && options.functionName.trim() !== '') { + this.idempotencyKeyPrefix = `${this.idempotencyKeyPrefix}.${options.functionName}`; + } } /**