diff --git a/package-lock.json b/package-lock.json index cda483229d..e743677bb0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15542,15 +15542,14 @@ }, "packages/commons": { "name": "@aws-lambda-powertools/commons", - "version": "1.2.1", + "version": "1.4.0", "license": "MIT-0" }, "packages/logger": { "name": "@aws-lambda-powertools/logger", - "version": "1.2.1", + "version": "1.4.0", "license": "MIT", "dependencies": { - "@aws-lambda-powertools/commons": "^1.2.1", "lodash.clonedeep": "^4.5.0", "lodash.merge": "^4.6.2", "lodash.pickby": "^4.6.0" @@ -15563,11 +15562,8 @@ }, "packages/metrics": { "name": "@aws-lambda-powertools/metrics", - "version": "1.2.1", + "version": "1.4.0", "license": "MIT-0", - "dependencies": { - "@aws-lambda-powertools/commons": "^1.2.1" - }, "devDependencies": { "@types/promise-retry": "^1.1.3", "promise-retry": "^2.0.1" @@ -15575,10 +15571,9 @@ }, "packages/tracer": { "name": "@aws-lambda-powertools/tracer", - "version": "1.2.1", + "version": "1.4.0", "license": "MIT-0", "dependencies": { - "@aws-lambda-powertools/commons": "^1.2.1", "aws-xray-sdk-core": "^3.3.6" }, "devDependencies": { @@ -15805,7 +15800,6 @@ "@aws-lambda-powertools/logger": { "version": "file:packages/logger", "requires": { - "@aws-lambda-powertools/commons": "^1.2.1", "@types/lodash.clonedeep": "^4.5.7", "@types/lodash.merge": "^4.6.7", "@types/lodash.pickby": "^4.6.7", @@ -15817,7 +15811,6 @@ "@aws-lambda-powertools/metrics": { "version": "file:packages/metrics", "requires": { - "@aws-lambda-powertools/commons": "^1.2.1", "@types/promise-retry": "^1.1.3", "promise-retry": "^2.0.1" } @@ -15825,7 +15818,6 @@ "@aws-lambda-powertools/tracer": { "version": "file:packages/tracer", "requires": { - "@aws-lambda-powertools/commons": "^1.2.1", "@aws-sdk/client-dynamodb": "^3.100.0", "@types/promise-retry": "^1.1.3", "aws-xray-sdk-core": "^3.3.6", diff --git a/package.json b/package.json index 211dcd6919..0affe9d6d4 100644 --- a/package.json +++ b/package.json @@ -51,10 +51,8 @@ }, "homepage": "https://github.com/awslabs/aws-lambda-powertools-typescript#readme", "devDependencies": { - "@aws-cdk/cx-api": "^2.17.0", "@aws-cdk/cloudformation-diff": "^2.17.0", - "aws-cdk-lib": "^2.17.0", - "constructs": "^10.0.92", + "@aws-cdk/cx-api": "^2.17.0", "@commitlint/cli": "^17.0.0", "@middy/core": "^2.5.6", "@types/aws-lambda": "^8.10.72", @@ -65,8 +63,10 @@ "@typescript-eslint/parser": "^5.12.1", "archiver": "^5.3.0", "aws-cdk": "^2.17.0", + "aws-cdk-lib": "^2.17.0", "aws-sdk": "^2.1082.0", "cdk-assets": "^2.17.0", + "constructs": "^10.0.92", "esbuild": "^0.14.23", "eslint": "^8.4.0", "eslint-import-resolver-node": "^0.3.6", @@ -94,4 +94,4 @@ "dependencies": { "hosted-git-info": "^5.0.0" } -} \ No newline at end of file +} diff --git a/packages/idempotency/jest.config.js b/packages/idempotency/jest.config.js index dd0e63cc41..8f1701110c 100644 --- a/packages/idempotency/jest.config.js +++ b/packages/idempotency/jest.config.js @@ -38,8 +38,5 @@ module.exports = { 'json-summary', 'text', 'lcov' - ], - 'setupFiles': [ - '/tests/helpers/populateEnvironmentVariables.ts' ] }; \ No newline at end of file diff --git a/packages/idempotency/package-lock.json b/packages/idempotency/package-lock.json new file mode 100644 index 0000000000..29fef4816a --- /dev/null +++ b/packages/idempotency/package-lock.json @@ -0,0 +1,3294 @@ +{ + "name": "@aws-lambda-powertools/idempotency", + "version": "0.0.11", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@aws-lambda-powertools/idempotency", + "version": "0.0.11", + "license": "MIT", + "dependencies": { + "@aws-lambda-powertools/commons": "^1.2.1", + "@aws-sdk/lib-dynamodb": "^3.170.0" + }, + "devDependencies": { + "aws-sdk-client-mock": "^2.0.0", + "aws-sdk-client-mock-jest": "^2.0.0" + } + }, + "node_modules/@aws-crypto/ie11-detection": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-2.0.2.tgz", + "integrity": "sha512-5XDMQY98gMAf/WRTic5G++jfmS/VLM0rwpiOpaainKi4L0nqWMSB1SzsrEG5rjFZGYN6ZAefO+/Yta2dFM0kMw==", + "peer": true, + "dependencies": { + "tslib": "^1.11.1" + } + }, + "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==", + "peer": true + }, + "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==", + "peer": true, + "dependencies": { + "@aws-crypto/ie11-detection": "^2.0.0", + "@aws-crypto/sha256-js": "^2.0.0", + "@aws-crypto/supports-web-crypto": "^2.0.0", + "@aws-crypto/util": "^2.0.0", + "@aws-sdk/types": "^3.1.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "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==", + "peer": true + }, + "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==", + "peer": true, + "dependencies": { + "@aws-crypto/util": "^2.0.0", + "@aws-sdk/types": "^3.1.0", + "tslib": "^1.11.1" + } + }, + "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==", + "peer": true + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-2.0.2.tgz", + "integrity": "sha512-6mbSsLHwZ99CTOOswvCRP3C+VCWnzBf+1SnbWxzzJ9lR0mA0JnY2JEAhp8rqmTE0GPFy88rrM27ffgp62oErMQ==", + "peer": true, + "dependencies": { + "tslib": "^1.11.1" + } + }, + "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==", + "peer": true + }, + "node_modules/@aws-crypto/util": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-2.0.2.tgz", + "integrity": "sha512-Lgu5v/0e/BcrZ5m/IWqzPUf3UYFTy/PpeED+uc9SWUR1iZQL8XXbGQg10UfllwwBryO3hFF5dizK+78aoXC1eA==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "^3.110.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "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==", + "peer": true + }, + "node_modules/@aws-lambda-powertools/commons": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@aws-lambda-powertools/commons/-/commons-1.2.1.tgz", + "integrity": "sha512-wHdAgzXQfRqcm6kIuxrQjKL8x02sVTMc7rcMJPkHU1DsGNL7Z3g0H+tkrlmFimGkRqPv724J2OqNdEvBJKaoMQ==" + }, + "node_modules/@aws-sdk/abort-controller": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.201.0.tgz", + "integrity": "sha512-xJ984k+CKlGjBmvNarzM8Y+b6X4L1Zt0TycQmVBJq7fAr/ju9l13pQIoXR5WlDIW1FkGeVczF5Nu6fN46SCORQ==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-dynamodb": { + "version": "3.202.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.202.0.tgz", + "integrity": "sha512-/S8+YqNQmIDMAkn40bIO9Fww1Lqzc1oSX82xUhzn4/k8UE36S9/pVDYgE3Nu8tHCqf71vvJUrVPiwj+9u7DDsg==", + "peer": true, + "dependencies": { + "@aws-crypto/sha256-browser": "2.0.0", + "@aws-crypto/sha256-js": "2.0.0", + "@aws-sdk/client-sts": "3.202.0", + "@aws-sdk/config-resolver": "3.201.0", + "@aws-sdk/credential-provider-node": "3.202.0", + "@aws-sdk/fetch-http-handler": "3.201.0", + "@aws-sdk/hash-node": "3.201.0", + "@aws-sdk/invalid-dependency": "3.201.0", + "@aws-sdk/middleware-content-length": "3.201.0", + "@aws-sdk/middleware-endpoint": "3.201.0", + "@aws-sdk/middleware-endpoint-discovery": "3.201.0", + "@aws-sdk/middleware-host-header": "3.201.0", + "@aws-sdk/middleware-logger": "3.201.0", + "@aws-sdk/middleware-recursion-detection": "3.201.0", + "@aws-sdk/middleware-retry": "3.201.0", + "@aws-sdk/middleware-serde": "3.201.0", + "@aws-sdk/middleware-signing": "3.201.0", + "@aws-sdk/middleware-stack": "3.201.0", + "@aws-sdk/middleware-user-agent": "3.201.0", + "@aws-sdk/node-config-provider": "3.201.0", + "@aws-sdk/node-http-handler": "3.201.0", + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/smithy-client": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/url-parser": "3.201.0", + "@aws-sdk/util-base64-browser": "3.188.0", + "@aws-sdk/util-base64-node": "3.201.0", + "@aws-sdk/util-body-length-browser": "3.188.0", + "@aws-sdk/util-body-length-node": "3.201.0", + "@aws-sdk/util-defaults-mode-browser": "3.201.0", + "@aws-sdk/util-defaults-mode-node": "3.201.0", + "@aws-sdk/util-endpoints": "3.202.0", + "@aws-sdk/util-user-agent-browser": "3.201.0", + "@aws-sdk/util-user-agent-node": "3.201.0", + "@aws-sdk/util-utf8-browser": "3.188.0", + "@aws-sdk/util-utf8-node": "3.201.0", + "@aws-sdk/util-waiter": "3.201.0", + "tslib": "^2.3.1", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.202.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.202.0.tgz", + "integrity": "sha512-c0impiZUbJeB5AdyZyER81tsqF9bxxaEz6p2LYkTn62NWVXPWEUo/1CHQRj36MUzorz1xiWKIN0NPgK6GBJkPQ==", + "peer": true, + "dependencies": { + "@aws-crypto/sha256-browser": "2.0.0", + "@aws-crypto/sha256-js": "2.0.0", + "@aws-sdk/config-resolver": "3.201.0", + "@aws-sdk/fetch-http-handler": "3.201.0", + "@aws-sdk/hash-node": "3.201.0", + "@aws-sdk/invalid-dependency": "3.201.0", + "@aws-sdk/middleware-content-length": "3.201.0", + "@aws-sdk/middleware-endpoint": "3.201.0", + "@aws-sdk/middleware-host-header": "3.201.0", + "@aws-sdk/middleware-logger": "3.201.0", + "@aws-sdk/middleware-recursion-detection": "3.201.0", + "@aws-sdk/middleware-retry": "3.201.0", + "@aws-sdk/middleware-serde": "3.201.0", + "@aws-sdk/middleware-stack": "3.201.0", + "@aws-sdk/middleware-user-agent": "3.201.0", + "@aws-sdk/node-config-provider": "3.201.0", + "@aws-sdk/node-http-handler": "3.201.0", + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/smithy-client": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/url-parser": "3.201.0", + "@aws-sdk/util-base64-browser": "3.188.0", + "@aws-sdk/util-base64-node": "3.201.0", + "@aws-sdk/util-body-length-browser": "3.188.0", + "@aws-sdk/util-body-length-node": "3.201.0", + "@aws-sdk/util-defaults-mode-browser": "3.201.0", + "@aws-sdk/util-defaults-mode-node": "3.201.0", + "@aws-sdk/util-endpoints": "3.202.0", + "@aws-sdk/util-user-agent-browser": "3.201.0", + "@aws-sdk/util-user-agent-node": "3.201.0", + "@aws-sdk/util-utf8-browser": "3.188.0", + "@aws-sdk/util-utf8-node": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sts": { + "version": "3.202.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.202.0.tgz", + "integrity": "sha512-WGRFzODig8+cZR903q3fa7OAzGigSuzD9AoK+ybefQa7bxSuhT2ous4GNPOJz9WYWvugEPyrJu8vbG35IoF1ZQ==", + "peer": true, + "dependencies": { + "@aws-crypto/sha256-browser": "2.0.0", + "@aws-crypto/sha256-js": "2.0.0", + "@aws-sdk/config-resolver": "3.201.0", + "@aws-sdk/credential-provider-node": "3.202.0", + "@aws-sdk/fetch-http-handler": "3.201.0", + "@aws-sdk/hash-node": "3.201.0", + "@aws-sdk/invalid-dependency": "3.201.0", + "@aws-sdk/middleware-content-length": "3.201.0", + "@aws-sdk/middleware-endpoint": "3.201.0", + "@aws-sdk/middleware-host-header": "3.201.0", + "@aws-sdk/middleware-logger": "3.201.0", + "@aws-sdk/middleware-recursion-detection": "3.201.0", + "@aws-sdk/middleware-retry": "3.201.0", + "@aws-sdk/middleware-sdk-sts": "3.201.0", + "@aws-sdk/middleware-serde": "3.201.0", + "@aws-sdk/middleware-signing": "3.201.0", + "@aws-sdk/middleware-stack": "3.201.0", + "@aws-sdk/middleware-user-agent": "3.201.0", + "@aws-sdk/node-config-provider": "3.201.0", + "@aws-sdk/node-http-handler": "3.201.0", + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/smithy-client": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/url-parser": "3.201.0", + "@aws-sdk/util-base64-browser": "3.188.0", + "@aws-sdk/util-base64-node": "3.201.0", + "@aws-sdk/util-body-length-browser": "3.188.0", + "@aws-sdk/util-body-length-node": "3.201.0", + "@aws-sdk/util-defaults-mode-browser": "3.201.0", + "@aws-sdk/util-defaults-mode-node": "3.201.0", + "@aws-sdk/util-endpoints": "3.202.0", + "@aws-sdk/util-user-agent-browser": "3.201.0", + "@aws-sdk/util-user-agent-node": "3.201.0", + "@aws-sdk/util-utf8-browser": "3.188.0", + "@aws-sdk/util-utf8-node": "3.201.0", + "fast-xml-parser": "4.0.11", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/config-resolver": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.201.0.tgz", + "integrity": "sha512-6YLIel7OGMGi+r8XC1A54cQJRIpx/NJ4fBALy44zFpQ+fdJUEmw4daUf1LECmAQiPA2Pr/hD0nBtX+wiiTf5/g==", + "peer": true, + "dependencies": { + "@aws-sdk/signature-v4": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/util-config-provider": "3.201.0", + "@aws-sdk/util-middleware": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.201.0.tgz", + "integrity": "sha512-g2MJsowzFhSsIOITUjYp7EzWFeHINjEP526Uf+5z2/p2kxQVwYYWZQK7j+tPE2Bk3MEjGOCmVHbbE7IFj0rNHw==", + "peer": true, + "dependencies": { + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-imds": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.201.0.tgz", + "integrity": "sha512-i8U2k3/L3iUWJJ1GSlwVBMfLQ2OTUT97E8yJi/xz5GavYuPOsUQWQe4fp7WGQivxh+AqybXAGFUCYub6zfUqag==", + "peer": true, + "dependencies": { + "@aws-sdk/node-config-provider": "3.201.0", + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/url-parser": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.202.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.202.0.tgz", + "integrity": "sha512-d0kiYMpGzAq3EBXgEJ1SdeoMXVf3lk6NKHDi/Gy8LB03sZqgc5cY4XFCnY3cqE3DNWWZNR26M4j/KiA0LIjAVA==", + "peer": true, + "dependencies": { + "@aws-sdk/credential-provider-env": "3.201.0", + "@aws-sdk/credential-provider-imds": "3.201.0", + "@aws-sdk/credential-provider-sso": "3.202.0", + "@aws-sdk/credential-provider-web-identity": "3.201.0", + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/shared-ini-file-loader": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.202.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.202.0.tgz", + "integrity": "sha512-/uHNs3c1O3oFpH7z9nnpjyg8NKNyRbNxUDIHkuHkNSUUKXpfBisDX6TMbD4VcflGuNdkbT+8spkw5vsE8ox3ig==", + "peer": true, + "dependencies": { + "@aws-sdk/credential-provider-env": "3.201.0", + "@aws-sdk/credential-provider-imds": "3.201.0", + "@aws-sdk/credential-provider-ini": "3.202.0", + "@aws-sdk/credential-provider-process": "3.201.0", + "@aws-sdk/credential-provider-sso": "3.202.0", + "@aws-sdk/credential-provider-web-identity": "3.201.0", + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/shared-ini-file-loader": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.201.0.tgz", + "integrity": "sha512-jTK3HSZgNj/hVrWb0wuF/cPUWSJYoRI/80fnN55o6QLS8WWIgOI8o2PNeVTAT5OrKioSoN4fgKTeUm3DZy3npQ==", + "peer": true, + "dependencies": { + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/shared-ini-file-loader": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.202.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.202.0.tgz", + "integrity": "sha512-EBUY/qKboJwy3qxPHiD/LAnhzga4xR1p++QMoxg2BKgkgwlvGb23lYGr5DSCNhdtJj5o165YZDbGYH+PKn2NVw==", + "peer": true, + "dependencies": { + "@aws-sdk/client-sso": "3.202.0", + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/shared-ini-file-loader": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.201.0.tgz", + "integrity": "sha512-U54bqhYaClPVZfswgknhlICp3BAtKXpOgHQCUF8cko5xUgbL4lVgd1rC3lWviGFMQAaTIF3QOXyEouemxr3VXw==", + "peer": true, + "dependencies": { + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/endpoint-cache": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.201.0.tgz", + "integrity": "sha512-QgT4Wm19yQ/HbvxNeYaR7m9uEYhW+0YY9nSpnRLHmhMJP90kmt9ANESIHCukPxc6ecDEZXIo7C2rica9P3H/ew==", + "peer": true, + "dependencies": { + "mnemonist": "0.38.3", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/fetch-http-handler": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.201.0.tgz", + "integrity": "sha512-uiEoH79j6WOpbp4THcpvD9XmD+vPgy+00oyYXjtZqJnv2PM/9b6tGWKTdI+TJW4P/oPv7HP7JmRlkGaTnkIdXw==", + "peer": true, + "dependencies": { + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/querystring-builder": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/util-base64-browser": "3.188.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/hash-node": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.201.0.tgz", + "integrity": "sha512-WJsMZg5/TMoWnLM+0NuwLwFzHsi89Bi9J1Dt7JdJHXFLoEZV54FEz1PK/Sq5NOldhVljpXQwWOB2dHA2wxFztg==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.201.0", + "@aws-sdk/util-buffer-from": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/invalid-dependency": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.201.0.tgz", + "integrity": "sha512-f/zgntOfIozNyKSaG9dvHjjBaR3y20kYNswMYkSuCM2NIT5LpyHiiq5I11TwaocatUFcDztWpcsv7vHpIgI5Ig==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/is-array-buffer": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.201.0.tgz", + "integrity": "sha512-UPez5qLh3dNgt0DYnPD/q0mVJY84rA17QE26hVNOW3fAji8W2wrwrxdacWOxyXvlxWsVRcKmr+lay1MDqpAMfg==", + "peer": true, + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/lib-dynamodb": { + "version": "3.202.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.202.0.tgz", + "integrity": "sha512-VJSIDw+meJKVBXz4pqnSSbxPMMfq4LhhFsVwmsLtNIHEg1evi0LKnSl+vQROOAWjVruUGk/L2Y1uluLOccn1kA==", + "dependencies": { + "@aws-sdk/util-dynamodb": "3.202.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.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.201.0.tgz", + "integrity": "sha512-p4G9AtdrKO8A3Z4RyZiy0isEYwuge7bQRBS7UzcGkcIOhJONq2pcM+gRZYz+NWvfYYNWUg5uODsFQfU8342yKg==", + "peer": true, + "dependencies": { + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-endpoint": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.201.0.tgz", + "integrity": "sha512-F3JlXo5GusbeZR956hA9VxmDxUeg77Xh6o8fveAE2+G4Bjcb1iq9jPNlw6A14vDj3oTKenv2LLnjL2OIfl6hRA==", + "peer": true, + "dependencies": { + "@aws-sdk/middleware-serde": "3.201.0", + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/signature-v4": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/url-parser": "3.201.0", + "@aws-sdk/util-config-provider": "3.201.0", + "@aws-sdk/util-middleware": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-endpoint-discovery": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.201.0.tgz", + "integrity": "sha512-EHQ+AH/bflmfM2qDN3Aa2ufhw2irv6+FE/13yW09KsunaKiuSyg7Clh6+T8ESw3fCaI4IE2ol0d6HNwJ4JLOVQ==", + "peer": true, + "dependencies": { + "@aws-sdk/config-resolver": "3.201.0", + "@aws-sdk/endpoint-cache": "3.201.0", + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.201.0.tgz", + "integrity": "sha512-7KNzdV7nFcKAoahvgGAlzsOq9FFDsU5h3w2iPtVdJhz6ZRDH/2v6WFeUCji+UNZip36gFfMPivoO8Y5smb5r/A==", + "peer": true, + "dependencies": { + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.201.0.tgz", + "integrity": "sha512-kYLsa9x3oUJxYU7V5KOO50Kl7b0kk+I4ltkrdarLvvXcVI7ZXmWHzHLT2dkUhj8S0ceVdi0FYHVPJ3GoE8re4A==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.201.0.tgz", + "integrity": "sha512-NGOr+n559ZcJLdFoJR8LNGdrOJFIp2BTuWEDYeicNdNb0bETTXrkzcfT1BRhV9CWqCDmjFvjdrzbhS0cw/UUGA==", + "peer": true, + "dependencies": { + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-retry": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.201.0.tgz", + "integrity": "sha512-4jQjSKCpSc4oB1X9nNq4FbIAwQrr+mvmUSmg/oe2Llf42Ak1G9gg3rNTtQdfzA/wNMlL4ZFfF5Br+uz06e1hnQ==", + "peer": true, + "dependencies": { + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/service-error-classification": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/util-middleware": "3.201.0", + "tslib": "^2.3.1", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-sts": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.201.0.tgz", + "integrity": "sha512-clZuXcoN0mAP4JH5C6pW5+0tdF25+fpFJqE7GNRjjH/NYNk6ImVI0Kq2espEWwVBuaS0/chTDK3b+pK8YOWdhw==", + "peer": true, + "dependencies": { + "@aws-sdk/middleware-signing": "3.201.0", + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/signature-v4": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-serde": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.201.0.tgz", + "integrity": "sha512-Z7AzIuqEDvsZmp80zeT1oYxsoB8uQZby20Z8kF6/vNoq3sIzaGf/wHeNn0p+Vgo2auGSbZcVUZKoDptQLSLwIQ==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-signing": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.201.0.tgz", + "integrity": "sha512-08ri5+mB28tva9RjVIXFcUP5lRTx+Pj8C2HYqF2GL5H3uAo+h3RQ++fEG1uwUMLf7tCEFivcw6SHA1KmCnB7+w==", + "peer": true, + "dependencies": { + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/signature-v4": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/util-middleware": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-stack": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.201.0.tgz", + "integrity": "sha512-lqHYSBP5FBxzA5w5XiYYYpfXabFzleXonqRkqZts1tapNJ4sOd+itiKG8JoNP7LDOwJ8qxNW/a33/gQeh3wkwQ==", + "peer": true, + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.201.0.tgz", + "integrity": "sha512-/rYZ93WN1gDJudXis/0382CEoTqRa4qZJA608u2EPWs5aiMocUrm7pjH5XvKm2OYX8K/lyaMSBvL2OTIMzXGaQ==", + "peer": true, + "dependencies": { + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/node-config-provider": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.201.0.tgz", + "integrity": "sha512-JO0K2qPTYn+pPC7g8rWr1oueg9CqGCkYbINuAuz79vjToOLUQnZT9GiFm7QADe6J6RT1oGEKRQabNaJnp8cFpQ==", + "peer": true, + "dependencies": { + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/shared-ini-file-loader": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/node-http-handler": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.201.0.tgz", + "integrity": "sha512-bWjXBd4WCiQcV4PwY+eFnlz9tZ4UiqfiJteav4MDt8YWkVlsVnR8RutmVSm3KZZjO2tJNSrla0ZWBebkNnI/Xg==", + "peer": true, + "dependencies": { + "@aws-sdk/abort-controller": "3.201.0", + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/querystring-builder": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/property-provider": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.201.0.tgz", + "integrity": "sha512-lVMP75VsYHIW04uYbkjA0I8Bb7b+aEj6PBBLdFoA22S0uCeJOD42OSr2Gtg2fToDGO7LQJw/K2D+LMCYKfZ3vQ==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/protocol-http": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.201.0.tgz", + "integrity": "sha512-RdOc1elWFpj8MogxG87nkhtylw0a+OD7W8WFM+Gw4yJMkl7cwW42VIBFfb0+KCGZfIQltIeSLRvfe3WvVPyo7Q==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/querystring-builder": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.201.0.tgz", + "integrity": "sha512-FgQnVHpYR19w/HmHEgWpykCn9tdogW0n45Ins6LBCo2aImDf9kBATD4xgN/F2rtogGuLGgu5LIIMHIOj1Tzs/w==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.201.0", + "@aws-sdk/util-uri-escape": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/querystring-parser": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.201.0.tgz", + "integrity": "sha512-vS9Ljbqrwi0sIKYxgyZYJUN1AcE291hvuqwty9etgD2w/26SbWiMhjIW/fXJUOZjUvGKkYCpbivJYSzAGAuWfQ==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/service-error-classification": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.201.0.tgz", + "integrity": "sha512-Pfcfmurgq8UpM0rXco6FVblcruqN4Mo3TW8/yaXrbctWpmdNT/8v19fffQIIgk94TU8Vf/nPJ7E5DXL7MZr4Fw==", + "peer": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/shared-ini-file-loader": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.201.0.tgz", + "integrity": "sha512-Pbxk0TXep0yI8MnK7Prly6JuBm5Me9AITav8/zPEgTZ3fMhXhQhhiuQcuTCI9GeosSzoiu8VvK53oPtBZZFnXQ==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.201.0.tgz", + "integrity": "sha512-zEHoG1/hzJq169slggkPy1SN9YPWI78Bbe/MvHGYmCmQDspblu60JSBIbAatNqAxAmcWKc2HqpyGKjCkMG94ZA==", + "peer": true, + "dependencies": { + "@aws-sdk/is-array-buffer": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/util-hex-encoding": "3.201.0", + "@aws-sdk/util-middleware": "3.201.0", + "@aws-sdk/util-uri-escape": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/smithy-client": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.201.0.tgz", + "integrity": "sha512-cL87Jgxczee8YFkWGWKQ2Ze0vjn4+eCa1kDvEYMCOQvNujTuFgatXLgije5a7nVkSnL9WLoIP7Y7fsBGrKfMnQ==", + "peer": true, + "dependencies": { + "@aws-sdk/middleware-stack": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.201.0.tgz", + "integrity": "sha512-RCQj2pQyHD330Jd4c5CHJ87k2ZqC3Mmtl6nhwH1dy3vbnGUpc3q+3yinOKoTAY934kIa7ia32Y/2EjuyHxaj1A==", + "peer": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/url-parser": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.201.0.tgz", + "integrity": "sha512-V15aqj0tj4Y79VpuIdHUvX4Nvn4hYPB0RAn/qg5CCComIl0doLOirAQtW1MOBOyctdRlD9Uv7d1QdPLzJZMHjQ==", + "peer": true, + "dependencies": { + "@aws-sdk/querystring-parser": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/util-base64-browser": { + "version": "3.188.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64-browser/-/util-base64-browser-3.188.0.tgz", + "integrity": "sha512-qlH+5NZBLiyKziL335BEPedYxX6j+p7KFRWXvDQox9S+s+gLCayednpK+fteOhBenCcR9fUZOVuAPScy1I8qCg==", + "peer": true, + "dependencies": { + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/util-base64-node": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64-node/-/util-base64-node-3.201.0.tgz", + "integrity": "sha512-ydZqNpB3l5kiicInpPDExPb5xHI7uyVIa1vMupnuIrJ412iNb0F2+K8LlFynzw6fSJShVKnqFcWOYRA96z1iIw==", + "peer": true, + "dependencies": { + "@aws-sdk/util-buffer-from": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-body-length-browser": { + "version": "3.188.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.188.0.tgz", + "integrity": "sha512-8VpnwFWXhnZ/iRSl9mTf+VKOX9wDE8QtN4bj9pBfxwf90H1X7E8T6NkiZD3k+HubYf2J94e7DbeHs7fuCPW5Qg==", + "peer": true, + "dependencies": { + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/util-body-length-node": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.201.0.tgz", + "integrity": "sha512-q+gwQoLn/DOwirb2hgZJeEwo1D3vLhoD6FfSV42Ecfvtb4jHnWReWMHguujfCubuDgZCrMEvYQzuocS75HHsbA==", + "peer": true, + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-buffer-from": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.201.0.tgz", + "integrity": "sha512-s6Wjltd9vU+vR3n0pqSPmNDcrrkrVTdV4t7x2zz3nDsFKTI77iVNafDmuaUlOA/bIlpjCJqaWecoVrZmEKeR7A==", + "peer": true, + "dependencies": { + "@aws-sdk/is-array-buffer": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-config-provider": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.201.0.tgz", + "integrity": "sha512-cCRJlnRRP8vrLJomzJRBIyiyohsjJKmnIaQ9t0tAhGCywZbyjx6TlpYRZYfVWo+MwdF1Pi8ZScTrFPW0JuBOIQ==", + "peer": true, + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-defaults-mode-browser": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.201.0.tgz", + "integrity": "sha512-skRMAM+xrV/sDvvtHC81ExEKQEiZFaRrRdUT39fBX1SpGnFTo2wpv7XK+rAW2XopGgnLPytXLQD97Kub79o4zA==", + "peer": true, + "dependencies": { + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/types": "3.201.0", + "bowser": "^2.11.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@aws-sdk/util-defaults-mode-node": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.201.0.tgz", + "integrity": "sha512-9N5LXRhxigbkbEcjQ4nNXHuQxp0VFlbc2/5wbcuPjIKX/OROiQI4mYQ6nuSKk7eku5sNFb9FtEHeD/RZo8od6Q==", + "peer": true, + "dependencies": { + "@aws-sdk/config-resolver": "3.201.0", + "@aws-sdk/credential-provider-imds": "3.201.0", + "@aws-sdk/node-config-provider": "3.201.0", + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@aws-sdk/util-dynamodb": { + "version": "3.202.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.202.0.tgz", + "integrity": "sha512-rJqJ6XjtvM0GWi+g/T6BXXaICoCHOG1i++iznFoz9WE1xpCTd1dtXtjw29tfAuvF7f6+lIJQemc8TWoczxWj2g==", + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.202.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.202.0.tgz", + "integrity": "sha512-sNees5uDp7nfEbvzaA1DAHqoEvEb9ZOkdNH5gcj/FMBETbr00YtsuXsTZogTHQsX/otRTiudZBE3iH7R4SLSAQ==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-hex-encoding": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.201.0.tgz", + "integrity": "sha512-7t1vR1pVxKx0motd3X9rI3m/xNp78p3sHtP5yo4NP4ARpxyJ0fokBomY8ScaH2D/B+U5o9ARxldJUdMqyBlJcA==", + "peer": true, + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.201.0.tgz", + "integrity": "sha512-hPJgifWh/rADabLAk1C9xXA2B3O4NUmbU58KgBRgC1HksiiHGFVZObB5fkBH8US/XV2jwORkpSf4OhretXQuKg==", + "peer": true, + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-middleware": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.201.0.tgz", + "integrity": "sha512-iAitcEZo17IyKn4ku1IBgtomr25esu5OuSRjw5Or4bNOeqXB0w50cItf/9qft8LIhbvBEAUtNAYXvqNzvhTZdQ==", + "peer": true, + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-uri-escape": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.201.0.tgz", + "integrity": "sha512-TeTWbGx4LU2c5rx0obHeDFeO9HvwYwQtMh1yniBz00pQb6Qt6YVOETVQikRZ+XRQwEyCg/dA375UplIpiy54mA==", + "peer": true, + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.201.0.tgz", + "integrity": "sha512-iL2gyz7GuUVtZcMZpqvfxdFrl9hc28qpagymmJ/w2yhN86YNPHdK8Sx1Yo6VxNGVDCCWGb7tHXf7VP+U4Yv/Lg==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.201.0", + "bowser": "^2.11.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.201.0.tgz", + "integrity": "sha512-6lhhvwB3AZSISnYQpDGdlyTrzfYK2P9QYjy7vZEBRd9TSOaggiFICXe03ZvZfVOSeg0EInlMKn1fIHzPUHRuHQ==", + "peer": true, + "dependencies": { + "@aws-sdk/node-config-provider": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/util-utf8-browser": { + "version": "3.188.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.188.0.tgz", + "integrity": "sha512-jt627x0+jE+Ydr9NwkFstg3cUvgWh56qdaqAMDsqgRlKD21md/6G226z/Qxl7lb1VEW2LlmCx43ai/37Qwcj2Q==", + "peer": true, + "dependencies": { + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/util-utf8-node": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-node/-/util-utf8-node-3.201.0.tgz", + "integrity": "sha512-A+bJFR/1rHYOJg137E69L1sX0I+LH+xf9ZjMXG9BVO0hSo7yDPoJVpHrzTJyOc3tuRITjIGBv9Qi4TKcoOSi1A==", + "peer": true, + "dependencies": { + "@aws-sdk/util-buffer-from": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-waiter": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-waiter/-/util-waiter-3.201.0.tgz", + "integrity": "sha512-NE8+BkPDXq86oyVr9EKN1s+iN8GID8mhj6DbtEZKZES3fJ36xH7MldRylgCewgv1Qpd1W00M4c/mVvUx3zp7sg==", + "peer": true, + "dependencies": { + "@aws-sdk/abort-controller": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "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/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/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/@sinclair/typebox": { + "version": "0.24.42", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.42.tgz", + "integrity": "sha512-d+2AtrHGyWek2u2ITF0lHRIv6Tt7X0dEHW+0rP+5aDCEjC3fiN2RBjrLD0yU0at52BcZbRGxLbAtXiR0hFCjYw==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "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/@sinonjs/samsam": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.1.tgz", + "integrity": "sha512-cZ7rKJTLiE7u7Wi/v9Hc2fs3Ucc3jrWeMgPHbbTCeVAB2S0wOBbYlkJVeNSL04i7fdhT8wIbDq1zhC/PXTD2SA==", + "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/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "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/@types/node": { + "version": "18.7.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.19.tgz", + "integrity": "sha512-Sq1itGUKUX1ap7GgZlrzdBydjbsJL/NSQt/4wkAxUJ7/OS5c2WkoN6WSpWc2Yc5wtKMZOUA0VCs/j2XJadN3HA==", + "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", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.12", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.12.tgz", + "integrity": "sha512-Nz4MPhecOFArtm81gFQvQqdV7XYCrWKx5uUt6GNHredFHn1i2mtWqXTON7EPXMtNi1qjtjEM/VCHDhcHsAMLXQ==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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/bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", + "peer": true + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ci-info": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.4.0.tgz", + "integrity": "sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==", + "dev": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/diff": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", + "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "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/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "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/fast-xml-parser": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.11.tgz", + "integrity": "sha512-4aUg3aNRR/WjQAcpceODG1C3x3lFANXRo8+1biqfieHmg9pyMt7qB4lQV/Ta6sJCTbA5vfD8fnA8S54JATiFUA==", + "peer": true, + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "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/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/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-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/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/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/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "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/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/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mnemonist": { + "version": "0.38.3", + "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.3.tgz", + "integrity": "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==", + "peer": true, + "dependencies": { + "obliterator": "^1.6.1" + } + }, + "node_modules/nise": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.1.tgz", + "integrity": "sha512-yr5kW2THW1AkxVmCnKEh4nbYkJdB3I7LUkiUgOvEkOp414mc2UMaHMA7pjq1nYowhdoJZGwEKGaQVbxfpWj10A==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.8.3", + "@sinonjs/fake-timers": ">=5", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "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==", + "peer": 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/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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/pretty-format/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/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/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/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "peer": true + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "peer": true, + "bin": { + "uuid": "dist/bin/uuid" + } + } + }, + "dependencies": { + "@aws-crypto/ie11-detection": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-2.0.2.tgz", + "integrity": "sha512-5XDMQY98gMAf/WRTic5G++jfmS/VLM0rwpiOpaainKi4L0nqWMSB1SzsrEG5rjFZGYN6ZAefO+/Yta2dFM0kMw==", + "peer": true, + "requires": { + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true + } + } + }, + "@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==", + "peer": true, + "requires": { + "@aws-crypto/ie11-detection": "^2.0.0", + "@aws-crypto/sha256-js": "^2.0.0", + "@aws-crypto/supports-web-crypto": "^2.0.0", + "@aws-crypto/util": "^2.0.0", + "@aws-sdk/types": "^3.1.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true + } + } + }, + "@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==", + "peer": true, + "requires": { + "@aws-crypto/util": "^2.0.0", + "@aws-sdk/types": "^3.1.0", + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true + } + } + }, + "@aws-crypto/supports-web-crypto": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-2.0.2.tgz", + "integrity": "sha512-6mbSsLHwZ99CTOOswvCRP3C+VCWnzBf+1SnbWxzzJ9lR0mA0JnY2JEAhp8rqmTE0GPFy88rrM27ffgp62oErMQ==", + "peer": true, + "requires": { + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true + } + } + }, + "@aws-crypto/util": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-2.0.2.tgz", + "integrity": "sha512-Lgu5v/0e/BcrZ5m/IWqzPUf3UYFTy/PpeED+uc9SWUR1iZQL8XXbGQg10UfllwwBryO3hFF5dizK+78aoXC1eA==", + "peer": true, + "requires": { + "@aws-sdk/types": "^3.110.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true + } + } + }, + "@aws-lambda-powertools/commons": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@aws-lambda-powertools/commons/-/commons-1.2.1.tgz", + "integrity": "sha512-wHdAgzXQfRqcm6kIuxrQjKL8x02sVTMc7rcMJPkHU1DsGNL7Z3g0H+tkrlmFimGkRqPv724J2OqNdEvBJKaoMQ==" + }, + "@aws-sdk/abort-controller": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.201.0.tgz", + "integrity": "sha512-xJ984k+CKlGjBmvNarzM8Y+b6X4L1Zt0TycQmVBJq7fAr/ju9l13pQIoXR5WlDIW1FkGeVczF5Nu6fN46SCORQ==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/client-dynamodb": { + "version": "3.202.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.202.0.tgz", + "integrity": "sha512-/S8+YqNQmIDMAkn40bIO9Fww1Lqzc1oSX82xUhzn4/k8UE36S9/pVDYgE3Nu8tHCqf71vvJUrVPiwj+9u7DDsg==", + "peer": true, + "requires": { + "@aws-crypto/sha256-browser": "2.0.0", + "@aws-crypto/sha256-js": "2.0.0", + "@aws-sdk/client-sts": "3.202.0", + "@aws-sdk/config-resolver": "3.201.0", + "@aws-sdk/credential-provider-node": "3.202.0", + "@aws-sdk/fetch-http-handler": "3.201.0", + "@aws-sdk/hash-node": "3.201.0", + "@aws-sdk/invalid-dependency": "3.201.0", + "@aws-sdk/middleware-content-length": "3.201.0", + "@aws-sdk/middleware-endpoint": "3.201.0", + "@aws-sdk/middleware-endpoint-discovery": "3.201.0", + "@aws-sdk/middleware-host-header": "3.201.0", + "@aws-sdk/middleware-logger": "3.201.0", + "@aws-sdk/middleware-recursion-detection": "3.201.0", + "@aws-sdk/middleware-retry": "3.201.0", + "@aws-sdk/middleware-serde": "3.201.0", + "@aws-sdk/middleware-signing": "3.201.0", + "@aws-sdk/middleware-stack": "3.201.0", + "@aws-sdk/middleware-user-agent": "3.201.0", + "@aws-sdk/node-config-provider": "3.201.0", + "@aws-sdk/node-http-handler": "3.201.0", + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/smithy-client": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/url-parser": "3.201.0", + "@aws-sdk/util-base64-browser": "3.188.0", + "@aws-sdk/util-base64-node": "3.201.0", + "@aws-sdk/util-body-length-browser": "3.188.0", + "@aws-sdk/util-body-length-node": "3.201.0", + "@aws-sdk/util-defaults-mode-browser": "3.201.0", + "@aws-sdk/util-defaults-mode-node": "3.201.0", + "@aws-sdk/util-endpoints": "3.202.0", + "@aws-sdk/util-user-agent-browser": "3.201.0", + "@aws-sdk/util-user-agent-node": "3.201.0", + "@aws-sdk/util-utf8-browser": "3.188.0", + "@aws-sdk/util-utf8-node": "3.201.0", + "@aws-sdk/util-waiter": "3.201.0", + "tslib": "^2.3.1", + "uuid": "^8.3.2" + } + }, + "@aws-sdk/client-sso": { + "version": "3.202.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.202.0.tgz", + "integrity": "sha512-c0impiZUbJeB5AdyZyER81tsqF9bxxaEz6p2LYkTn62NWVXPWEUo/1CHQRj36MUzorz1xiWKIN0NPgK6GBJkPQ==", + "peer": true, + "requires": { + "@aws-crypto/sha256-browser": "2.0.0", + "@aws-crypto/sha256-js": "2.0.0", + "@aws-sdk/config-resolver": "3.201.0", + "@aws-sdk/fetch-http-handler": "3.201.0", + "@aws-sdk/hash-node": "3.201.0", + "@aws-sdk/invalid-dependency": "3.201.0", + "@aws-sdk/middleware-content-length": "3.201.0", + "@aws-sdk/middleware-endpoint": "3.201.0", + "@aws-sdk/middleware-host-header": "3.201.0", + "@aws-sdk/middleware-logger": "3.201.0", + "@aws-sdk/middleware-recursion-detection": "3.201.0", + "@aws-sdk/middleware-retry": "3.201.0", + "@aws-sdk/middleware-serde": "3.201.0", + "@aws-sdk/middleware-stack": "3.201.0", + "@aws-sdk/middleware-user-agent": "3.201.0", + "@aws-sdk/node-config-provider": "3.201.0", + "@aws-sdk/node-http-handler": "3.201.0", + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/smithy-client": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/url-parser": "3.201.0", + "@aws-sdk/util-base64-browser": "3.188.0", + "@aws-sdk/util-base64-node": "3.201.0", + "@aws-sdk/util-body-length-browser": "3.188.0", + "@aws-sdk/util-body-length-node": "3.201.0", + "@aws-sdk/util-defaults-mode-browser": "3.201.0", + "@aws-sdk/util-defaults-mode-node": "3.201.0", + "@aws-sdk/util-endpoints": "3.202.0", + "@aws-sdk/util-user-agent-browser": "3.201.0", + "@aws-sdk/util-user-agent-node": "3.201.0", + "@aws-sdk/util-utf8-browser": "3.188.0", + "@aws-sdk/util-utf8-node": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/client-sts": { + "version": "3.202.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.202.0.tgz", + "integrity": "sha512-WGRFzODig8+cZR903q3fa7OAzGigSuzD9AoK+ybefQa7bxSuhT2ous4GNPOJz9WYWvugEPyrJu8vbG35IoF1ZQ==", + "peer": true, + "requires": { + "@aws-crypto/sha256-browser": "2.0.0", + "@aws-crypto/sha256-js": "2.0.0", + "@aws-sdk/config-resolver": "3.201.0", + "@aws-sdk/credential-provider-node": "3.202.0", + "@aws-sdk/fetch-http-handler": "3.201.0", + "@aws-sdk/hash-node": "3.201.0", + "@aws-sdk/invalid-dependency": "3.201.0", + "@aws-sdk/middleware-content-length": "3.201.0", + "@aws-sdk/middleware-endpoint": "3.201.0", + "@aws-sdk/middleware-host-header": "3.201.0", + "@aws-sdk/middleware-logger": "3.201.0", + "@aws-sdk/middleware-recursion-detection": "3.201.0", + "@aws-sdk/middleware-retry": "3.201.0", + "@aws-sdk/middleware-sdk-sts": "3.201.0", + "@aws-sdk/middleware-serde": "3.201.0", + "@aws-sdk/middleware-signing": "3.201.0", + "@aws-sdk/middleware-stack": "3.201.0", + "@aws-sdk/middleware-user-agent": "3.201.0", + "@aws-sdk/node-config-provider": "3.201.0", + "@aws-sdk/node-http-handler": "3.201.0", + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/smithy-client": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/url-parser": "3.201.0", + "@aws-sdk/util-base64-browser": "3.188.0", + "@aws-sdk/util-base64-node": "3.201.0", + "@aws-sdk/util-body-length-browser": "3.188.0", + "@aws-sdk/util-body-length-node": "3.201.0", + "@aws-sdk/util-defaults-mode-browser": "3.201.0", + "@aws-sdk/util-defaults-mode-node": "3.201.0", + "@aws-sdk/util-endpoints": "3.202.0", + "@aws-sdk/util-user-agent-browser": "3.201.0", + "@aws-sdk/util-user-agent-node": "3.201.0", + "@aws-sdk/util-utf8-browser": "3.188.0", + "@aws-sdk/util-utf8-node": "3.201.0", + "fast-xml-parser": "4.0.11", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/config-resolver": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.201.0.tgz", + "integrity": "sha512-6YLIel7OGMGi+r8XC1A54cQJRIpx/NJ4fBALy44zFpQ+fdJUEmw4daUf1LECmAQiPA2Pr/hD0nBtX+wiiTf5/g==", + "peer": true, + "requires": { + "@aws-sdk/signature-v4": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/util-config-provider": "3.201.0", + "@aws-sdk/util-middleware": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/credential-provider-env": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.201.0.tgz", + "integrity": "sha512-g2MJsowzFhSsIOITUjYp7EzWFeHINjEP526Uf+5z2/p2kxQVwYYWZQK7j+tPE2Bk3MEjGOCmVHbbE7IFj0rNHw==", + "peer": true, + "requires": { + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/credential-provider-imds": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.201.0.tgz", + "integrity": "sha512-i8U2k3/L3iUWJJ1GSlwVBMfLQ2OTUT97E8yJi/xz5GavYuPOsUQWQe4fp7WGQivxh+AqybXAGFUCYub6zfUqag==", + "peer": true, + "requires": { + "@aws-sdk/node-config-provider": "3.201.0", + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/url-parser": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/credential-provider-ini": { + "version": "3.202.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.202.0.tgz", + "integrity": "sha512-d0kiYMpGzAq3EBXgEJ1SdeoMXVf3lk6NKHDi/Gy8LB03sZqgc5cY4XFCnY3cqE3DNWWZNR26M4j/KiA0LIjAVA==", + "peer": true, + "requires": { + "@aws-sdk/credential-provider-env": "3.201.0", + "@aws-sdk/credential-provider-imds": "3.201.0", + "@aws-sdk/credential-provider-sso": "3.202.0", + "@aws-sdk/credential-provider-web-identity": "3.201.0", + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/shared-ini-file-loader": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/credential-provider-node": { + "version": "3.202.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.202.0.tgz", + "integrity": "sha512-/uHNs3c1O3oFpH7z9nnpjyg8NKNyRbNxUDIHkuHkNSUUKXpfBisDX6TMbD4VcflGuNdkbT+8spkw5vsE8ox3ig==", + "peer": true, + "requires": { + "@aws-sdk/credential-provider-env": "3.201.0", + "@aws-sdk/credential-provider-imds": "3.201.0", + "@aws-sdk/credential-provider-ini": "3.202.0", + "@aws-sdk/credential-provider-process": "3.201.0", + "@aws-sdk/credential-provider-sso": "3.202.0", + "@aws-sdk/credential-provider-web-identity": "3.201.0", + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/shared-ini-file-loader": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/credential-provider-process": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.201.0.tgz", + "integrity": "sha512-jTK3HSZgNj/hVrWb0wuF/cPUWSJYoRI/80fnN55o6QLS8WWIgOI8o2PNeVTAT5OrKioSoN4fgKTeUm3DZy3npQ==", + "peer": true, + "requires": { + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/shared-ini-file-loader": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/credential-provider-sso": { + "version": "3.202.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.202.0.tgz", + "integrity": "sha512-EBUY/qKboJwy3qxPHiD/LAnhzga4xR1p++QMoxg2BKgkgwlvGb23lYGr5DSCNhdtJj5o165YZDbGYH+PKn2NVw==", + "peer": true, + "requires": { + "@aws-sdk/client-sso": "3.202.0", + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/shared-ini-file-loader": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/credential-provider-web-identity": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.201.0.tgz", + "integrity": "sha512-U54bqhYaClPVZfswgknhlICp3BAtKXpOgHQCUF8cko5xUgbL4lVgd1rC3lWviGFMQAaTIF3QOXyEouemxr3VXw==", + "peer": true, + "requires": { + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/endpoint-cache": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.201.0.tgz", + "integrity": "sha512-QgT4Wm19yQ/HbvxNeYaR7m9uEYhW+0YY9nSpnRLHmhMJP90kmt9ANESIHCukPxc6ecDEZXIo7C2rica9P3H/ew==", + "peer": true, + "requires": { + "mnemonist": "0.38.3", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/fetch-http-handler": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.201.0.tgz", + "integrity": "sha512-uiEoH79j6WOpbp4THcpvD9XmD+vPgy+00oyYXjtZqJnv2PM/9b6tGWKTdI+TJW4P/oPv7HP7JmRlkGaTnkIdXw==", + "peer": true, + "requires": { + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/querystring-builder": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/util-base64-browser": "3.188.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/hash-node": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.201.0.tgz", + "integrity": "sha512-WJsMZg5/TMoWnLM+0NuwLwFzHsi89Bi9J1Dt7JdJHXFLoEZV54FEz1PK/Sq5NOldhVljpXQwWOB2dHA2wxFztg==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.201.0", + "@aws-sdk/util-buffer-from": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/invalid-dependency": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.201.0.tgz", + "integrity": "sha512-f/zgntOfIozNyKSaG9dvHjjBaR3y20kYNswMYkSuCM2NIT5LpyHiiq5I11TwaocatUFcDztWpcsv7vHpIgI5Ig==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/is-array-buffer": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.201.0.tgz", + "integrity": "sha512-UPez5qLh3dNgt0DYnPD/q0mVJY84rA17QE26hVNOW3fAji8W2wrwrxdacWOxyXvlxWsVRcKmr+lay1MDqpAMfg==", + "peer": true, + "requires": { + "tslib": "^2.3.1" + } + }, + "@aws-sdk/lib-dynamodb": { + "version": "3.202.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.202.0.tgz", + "integrity": "sha512-VJSIDw+meJKVBXz4pqnSSbxPMMfq4LhhFsVwmsLtNIHEg1evi0LKnSl+vQROOAWjVruUGk/L2Y1uluLOccn1kA==", + "requires": { + "@aws-sdk/util-dynamodb": "3.202.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/middleware-content-length": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.201.0.tgz", + "integrity": "sha512-p4G9AtdrKO8A3Z4RyZiy0isEYwuge7bQRBS7UzcGkcIOhJONq2pcM+gRZYz+NWvfYYNWUg5uODsFQfU8342yKg==", + "peer": true, + "requires": { + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/middleware-endpoint": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.201.0.tgz", + "integrity": "sha512-F3JlXo5GusbeZR956hA9VxmDxUeg77Xh6o8fveAE2+G4Bjcb1iq9jPNlw6A14vDj3oTKenv2LLnjL2OIfl6hRA==", + "peer": true, + "requires": { + "@aws-sdk/middleware-serde": "3.201.0", + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/signature-v4": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/url-parser": "3.201.0", + "@aws-sdk/util-config-provider": "3.201.0", + "@aws-sdk/util-middleware": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/middleware-endpoint-discovery": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.201.0.tgz", + "integrity": "sha512-EHQ+AH/bflmfM2qDN3Aa2ufhw2irv6+FE/13yW09KsunaKiuSyg7Clh6+T8ESw3fCaI4IE2ol0d6HNwJ4JLOVQ==", + "peer": true, + "requires": { + "@aws-sdk/config-resolver": "3.201.0", + "@aws-sdk/endpoint-cache": "3.201.0", + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/middleware-host-header": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.201.0.tgz", + "integrity": "sha512-7KNzdV7nFcKAoahvgGAlzsOq9FFDsU5h3w2iPtVdJhz6ZRDH/2v6WFeUCji+UNZip36gFfMPivoO8Y5smb5r/A==", + "peer": true, + "requires": { + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/middleware-logger": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.201.0.tgz", + "integrity": "sha512-kYLsa9x3oUJxYU7V5KOO50Kl7b0kk+I4ltkrdarLvvXcVI7ZXmWHzHLT2dkUhj8S0ceVdi0FYHVPJ3GoE8re4A==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/middleware-recursion-detection": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.201.0.tgz", + "integrity": "sha512-NGOr+n559ZcJLdFoJR8LNGdrOJFIp2BTuWEDYeicNdNb0bETTXrkzcfT1BRhV9CWqCDmjFvjdrzbhS0cw/UUGA==", + "peer": true, + "requires": { + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/middleware-retry": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.201.0.tgz", + "integrity": "sha512-4jQjSKCpSc4oB1X9nNq4FbIAwQrr+mvmUSmg/oe2Llf42Ak1G9gg3rNTtQdfzA/wNMlL4ZFfF5Br+uz06e1hnQ==", + "peer": true, + "requires": { + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/service-error-classification": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/util-middleware": "3.201.0", + "tslib": "^2.3.1", + "uuid": "^8.3.2" + } + }, + "@aws-sdk/middleware-sdk-sts": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.201.0.tgz", + "integrity": "sha512-clZuXcoN0mAP4JH5C6pW5+0tdF25+fpFJqE7GNRjjH/NYNk6ImVI0Kq2espEWwVBuaS0/chTDK3b+pK8YOWdhw==", + "peer": true, + "requires": { + "@aws-sdk/middleware-signing": "3.201.0", + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/signature-v4": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/middleware-serde": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.201.0.tgz", + "integrity": "sha512-Z7AzIuqEDvsZmp80zeT1oYxsoB8uQZby20Z8kF6/vNoq3sIzaGf/wHeNn0p+Vgo2auGSbZcVUZKoDptQLSLwIQ==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/middleware-signing": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.201.0.tgz", + "integrity": "sha512-08ri5+mB28tva9RjVIXFcUP5lRTx+Pj8C2HYqF2GL5H3uAo+h3RQ++fEG1uwUMLf7tCEFivcw6SHA1KmCnB7+w==", + "peer": true, + "requires": { + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/signature-v4": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/util-middleware": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/middleware-stack": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.201.0.tgz", + "integrity": "sha512-lqHYSBP5FBxzA5w5XiYYYpfXabFzleXonqRkqZts1tapNJ4sOd+itiKG8JoNP7LDOwJ8qxNW/a33/gQeh3wkwQ==", + "peer": true, + "requires": { + "tslib": "^2.3.1" + } + }, + "@aws-sdk/middleware-user-agent": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.201.0.tgz", + "integrity": "sha512-/rYZ93WN1gDJudXis/0382CEoTqRa4qZJA608u2EPWs5aiMocUrm7pjH5XvKm2OYX8K/lyaMSBvL2OTIMzXGaQ==", + "peer": true, + "requires": { + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/node-config-provider": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.201.0.tgz", + "integrity": "sha512-JO0K2qPTYn+pPC7g8rWr1oueg9CqGCkYbINuAuz79vjToOLUQnZT9GiFm7QADe6J6RT1oGEKRQabNaJnp8cFpQ==", + "peer": true, + "requires": { + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/shared-ini-file-loader": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/node-http-handler": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.201.0.tgz", + "integrity": "sha512-bWjXBd4WCiQcV4PwY+eFnlz9tZ4UiqfiJteav4MDt8YWkVlsVnR8RutmVSm3KZZjO2tJNSrla0ZWBebkNnI/Xg==", + "peer": true, + "requires": { + "@aws-sdk/abort-controller": "3.201.0", + "@aws-sdk/protocol-http": "3.201.0", + "@aws-sdk/querystring-builder": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/property-provider": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.201.0.tgz", + "integrity": "sha512-lVMP75VsYHIW04uYbkjA0I8Bb7b+aEj6PBBLdFoA22S0uCeJOD42OSr2Gtg2fToDGO7LQJw/K2D+LMCYKfZ3vQ==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/protocol-http": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.201.0.tgz", + "integrity": "sha512-RdOc1elWFpj8MogxG87nkhtylw0a+OD7W8WFM+Gw4yJMkl7cwW42VIBFfb0+KCGZfIQltIeSLRvfe3WvVPyo7Q==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/querystring-builder": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.201.0.tgz", + "integrity": "sha512-FgQnVHpYR19w/HmHEgWpykCn9tdogW0n45Ins6LBCo2aImDf9kBATD4xgN/F2rtogGuLGgu5LIIMHIOj1Tzs/w==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.201.0", + "@aws-sdk/util-uri-escape": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/querystring-parser": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.201.0.tgz", + "integrity": "sha512-vS9Ljbqrwi0sIKYxgyZYJUN1AcE291hvuqwty9etgD2w/26SbWiMhjIW/fXJUOZjUvGKkYCpbivJYSzAGAuWfQ==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/service-error-classification": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.201.0.tgz", + "integrity": "sha512-Pfcfmurgq8UpM0rXco6FVblcruqN4Mo3TW8/yaXrbctWpmdNT/8v19fffQIIgk94TU8Vf/nPJ7E5DXL7MZr4Fw==", + "peer": true + }, + "@aws-sdk/shared-ini-file-loader": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.201.0.tgz", + "integrity": "sha512-Pbxk0TXep0yI8MnK7Prly6JuBm5Me9AITav8/zPEgTZ3fMhXhQhhiuQcuTCI9GeosSzoiu8VvK53oPtBZZFnXQ==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/signature-v4": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.201.0.tgz", + "integrity": "sha512-zEHoG1/hzJq169slggkPy1SN9YPWI78Bbe/MvHGYmCmQDspblu60JSBIbAatNqAxAmcWKc2HqpyGKjCkMG94ZA==", + "peer": true, + "requires": { + "@aws-sdk/is-array-buffer": "3.201.0", + "@aws-sdk/types": "3.201.0", + "@aws-sdk/util-hex-encoding": "3.201.0", + "@aws-sdk/util-middleware": "3.201.0", + "@aws-sdk/util-uri-escape": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/smithy-client": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.201.0.tgz", + "integrity": "sha512-cL87Jgxczee8YFkWGWKQ2Ze0vjn4+eCa1kDvEYMCOQvNujTuFgatXLgije5a7nVkSnL9WLoIP7Y7fsBGrKfMnQ==", + "peer": true, + "requires": { + "@aws-sdk/middleware-stack": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/types": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.201.0.tgz", + "integrity": "sha512-RCQj2pQyHD330Jd4c5CHJ87k2ZqC3Mmtl6nhwH1dy3vbnGUpc3q+3yinOKoTAY934kIa7ia32Y/2EjuyHxaj1A==", + "peer": true + }, + "@aws-sdk/url-parser": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.201.0.tgz", + "integrity": "sha512-V15aqj0tj4Y79VpuIdHUvX4Nvn4hYPB0RAn/qg5CCComIl0doLOirAQtW1MOBOyctdRlD9Uv7d1QdPLzJZMHjQ==", + "peer": true, + "requires": { + "@aws-sdk/querystring-parser": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/util-base64-browser": { + "version": "3.188.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64-browser/-/util-base64-browser-3.188.0.tgz", + "integrity": "sha512-qlH+5NZBLiyKziL335BEPedYxX6j+p7KFRWXvDQox9S+s+gLCayednpK+fteOhBenCcR9fUZOVuAPScy1I8qCg==", + "peer": true, + "requires": { + "tslib": "^2.3.1" + } + }, + "@aws-sdk/util-base64-node": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64-node/-/util-base64-node-3.201.0.tgz", + "integrity": "sha512-ydZqNpB3l5kiicInpPDExPb5xHI7uyVIa1vMupnuIrJ412iNb0F2+K8LlFynzw6fSJShVKnqFcWOYRA96z1iIw==", + "peer": true, + "requires": { + "@aws-sdk/util-buffer-from": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/util-body-length-browser": { + "version": "3.188.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.188.0.tgz", + "integrity": "sha512-8VpnwFWXhnZ/iRSl9mTf+VKOX9wDE8QtN4bj9pBfxwf90H1X7E8T6NkiZD3k+HubYf2J94e7DbeHs7fuCPW5Qg==", + "peer": true, + "requires": { + "tslib": "^2.3.1" + } + }, + "@aws-sdk/util-body-length-node": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.201.0.tgz", + "integrity": "sha512-q+gwQoLn/DOwirb2hgZJeEwo1D3vLhoD6FfSV42Ecfvtb4jHnWReWMHguujfCubuDgZCrMEvYQzuocS75HHsbA==", + "peer": true, + "requires": { + "tslib": "^2.3.1" + } + }, + "@aws-sdk/util-buffer-from": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.201.0.tgz", + "integrity": "sha512-s6Wjltd9vU+vR3n0pqSPmNDcrrkrVTdV4t7x2zz3nDsFKTI77iVNafDmuaUlOA/bIlpjCJqaWecoVrZmEKeR7A==", + "peer": true, + "requires": { + "@aws-sdk/is-array-buffer": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/util-config-provider": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.201.0.tgz", + "integrity": "sha512-cCRJlnRRP8vrLJomzJRBIyiyohsjJKmnIaQ9t0tAhGCywZbyjx6TlpYRZYfVWo+MwdF1Pi8ZScTrFPW0JuBOIQ==", + "peer": true, + "requires": { + "tslib": "^2.3.1" + } + }, + "@aws-sdk/util-defaults-mode-browser": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.201.0.tgz", + "integrity": "sha512-skRMAM+xrV/sDvvtHC81ExEKQEiZFaRrRdUT39fBX1SpGnFTo2wpv7XK+rAW2XopGgnLPytXLQD97Kub79o4zA==", + "peer": true, + "requires": { + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/types": "3.201.0", + "bowser": "^2.11.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/util-defaults-mode-node": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.201.0.tgz", + "integrity": "sha512-9N5LXRhxigbkbEcjQ4nNXHuQxp0VFlbc2/5wbcuPjIKX/OROiQI4mYQ6nuSKk7eku5sNFb9FtEHeD/RZo8od6Q==", + "peer": true, + "requires": { + "@aws-sdk/config-resolver": "3.201.0", + "@aws-sdk/credential-provider-imds": "3.201.0", + "@aws-sdk/node-config-provider": "3.201.0", + "@aws-sdk/property-provider": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/util-dynamodb": { + "version": "3.202.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.202.0.tgz", + "integrity": "sha512-rJqJ6XjtvM0GWi+g/T6BXXaICoCHOG1i++iznFoz9WE1xpCTd1dtXtjw29tfAuvF7f6+lIJQemc8TWoczxWj2g==", + "requires": { + "tslib": "^2.3.1" + } + }, + "@aws-sdk/util-endpoints": { + "version": "3.202.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.202.0.tgz", + "integrity": "sha512-sNees5uDp7nfEbvzaA1DAHqoEvEb9ZOkdNH5gcj/FMBETbr00YtsuXsTZogTHQsX/otRTiudZBE3iH7R4SLSAQ==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/util-hex-encoding": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.201.0.tgz", + "integrity": "sha512-7t1vR1pVxKx0motd3X9rI3m/xNp78p3sHtP5yo4NP4ARpxyJ0fokBomY8ScaH2D/B+U5o9ARxldJUdMqyBlJcA==", + "peer": true, + "requires": { + "tslib": "^2.3.1" + } + }, + "@aws-sdk/util-locate-window": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.201.0.tgz", + "integrity": "sha512-hPJgifWh/rADabLAk1C9xXA2B3O4NUmbU58KgBRgC1HksiiHGFVZObB5fkBH8US/XV2jwORkpSf4OhretXQuKg==", + "peer": true, + "requires": { + "tslib": "^2.3.1" + } + }, + "@aws-sdk/util-middleware": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.201.0.tgz", + "integrity": "sha512-iAitcEZo17IyKn4ku1IBgtomr25esu5OuSRjw5Or4bNOeqXB0w50cItf/9qft8LIhbvBEAUtNAYXvqNzvhTZdQ==", + "peer": true, + "requires": { + "tslib": "^2.3.1" + } + }, + "@aws-sdk/util-uri-escape": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.201.0.tgz", + "integrity": "sha512-TeTWbGx4LU2c5rx0obHeDFeO9HvwYwQtMh1yniBz00pQb6Qt6YVOETVQikRZ+XRQwEyCg/dA375UplIpiy54mA==", + "peer": true, + "requires": { + "tslib": "^2.3.1" + } + }, + "@aws-sdk/util-user-agent-browser": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.201.0.tgz", + "integrity": "sha512-iL2gyz7GuUVtZcMZpqvfxdFrl9hc28qpagymmJ/w2yhN86YNPHdK8Sx1Yo6VxNGVDCCWGb7tHXf7VP+U4Yv/Lg==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.201.0", + "bowser": "^2.11.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/util-user-agent-node": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.201.0.tgz", + "integrity": "sha512-6lhhvwB3AZSISnYQpDGdlyTrzfYK2P9QYjy7vZEBRd9TSOaggiFICXe03ZvZfVOSeg0EInlMKn1fIHzPUHRuHQ==", + "peer": true, + "requires": { + "@aws-sdk/node-config-provider": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/util-utf8-browser": { + "version": "3.188.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.188.0.tgz", + "integrity": "sha512-jt627x0+jE+Ydr9NwkFstg3cUvgWh56qdaqAMDsqgRlKD21md/6G226z/Qxl7lb1VEW2LlmCx43ai/37Qwcj2Q==", + "peer": true, + "requires": { + "tslib": "^2.3.1" + } + }, + "@aws-sdk/util-utf8-node": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-node/-/util-utf8-node-3.201.0.tgz", + "integrity": "sha512-A+bJFR/1rHYOJg137E69L1sX0I+LH+xf9ZjMXG9BVO0hSo7yDPoJVpHrzTJyOc3tuRITjIGBv9Qi4TKcoOSi1A==", + "peer": true, + "requires": { + "@aws-sdk/util-buffer-from": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@aws-sdk/util-waiter": { + "version": "3.201.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-waiter/-/util-waiter-3.201.0.tgz", + "integrity": "sha512-NE8+BkPDXq86oyVr9EKN1s+iN8GID8mhj6DbtEZKZES3fJ36xH7MldRylgCewgv1Qpd1W00M4c/mVvUx3zp7sg==", + "peer": true, + "requires": { + "@aws-sdk/abort-controller": "3.201.0", + "@aws-sdk/types": "3.201.0", + "tslib": "^2.3.1" + } + }, + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@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" + } + }, + "@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/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" + } + }, + "@sinclair/typebox": { + "version": "0.24.42", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.42.tgz", + "integrity": "sha512-d+2AtrHGyWek2u2ITF0lHRIv6Tt7X0dEHW+0rP+5aDCEjC3fiN2RBjrLD0yU0at52BcZbRGxLbAtXiR0hFCjYw==", + "dev": true + }, + "@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "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" + } + }, + "@sinonjs/samsam": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.1.tgz", + "integrity": "sha512-cZ7rKJTLiE7u7Wi/v9Hc2fs3Ucc3jrWeMgPHbbTCeVAB2S0wOBbYlkJVeNSL04i7fdhT8wIbDq1zhC/PXTD2SA==", + "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 + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@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/node": { + "version": "18.7.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.19.tgz", + "integrity": "sha512-Sq1itGUKUX1ap7GgZlrzdBydjbsJL/NSQt/4wkAxUJ7/OS5c2WkoN6WSpWc2Yc5wtKMZOUA0VCs/j2XJadN3HA==", + "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", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "@types/yargs": { + "version": "17.0.12", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.12.tgz", + "integrity": "sha512-Nz4MPhecOFArtm81gFQvQqdV7XYCrWKx5uUt6GNHredFHn1i2mtWqXTON7EPXMtNi1qjtjEM/VCHDhcHsAMLXQ==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "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" + } + }, + "bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", + "peer": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.4.0.tgz", + "integrity": "sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "diff": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", + "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "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 + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "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" + } + }, + "fast-xml-parser": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.11.tgz", + "integrity": "sha512-4aUg3aNRR/WjQAcpceODG1C3x3lFANXRo8+1biqfieHmg9pyMt7qB4lQV/Ta6sJCTbA5vfD8fnA8S54JATiFUA==", + "peer": true, + "requires": { + "strnum": "^1.0.5" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "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 + }, + "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" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "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 + }, + "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 + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mnemonist": { + "version": "0.38.3", + "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.3.tgz", + "integrity": "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==", + "peer": true, + "requires": { + "obliterator": "^1.6.1" + } + }, + "nise": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.1.tgz", + "integrity": "sha512-yr5kW2THW1AkxVmCnKEh4nbYkJdB3I7LUkiUgOvEkOp414mc2UMaHMA7pjq1nYowhdoJZGwEKGaQVbxfpWj10A==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.8.3", + "@sinonjs/fake-timers": ">=5", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "obliterator": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-1.6.1.tgz", + "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==", + "peer": 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" + } + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "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" + }, + "dependencies": { + "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 + } + } + }, + "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 + }, + "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" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "peer": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "peer": true + } + } +} diff --git a/packages/idempotency/package.json b/packages/idempotency/package.json index a782055d5a..4f2245813f 100644 --- a/packages/idempotency/package.json +++ b/packages/idempotency/package.json @@ -45,7 +45,8 @@ "url": "https://github.com/awslabs/aws-lambda-powertools-typescript/issues" }, "dependencies": { - "@aws-lambda-powertools/commons": "^1.2.1" + "@aws-lambda-powertools/commons": "^1.2.1", + "@aws-sdk/lib-dynamodb": "^3.170.0" }, "keywords": [ "aws", @@ -53,5 +54,9 @@ "powertools", "serverless", "nodejs" - ] -} \ No newline at end of file + ], + "devDependencies": { + "aws-sdk-client-mock": "^2.0.0", + "aws-sdk-client-mock-jest": "^2.0.0" + } +} diff --git a/packages/idempotency/src/EnvironmentVariablesService.ts b/packages/idempotency/src/EnvironmentVariablesService.ts new file mode 100644 index 0000000000..4d9892e307 --- /dev/null +++ b/packages/idempotency/src/EnvironmentVariablesService.ts @@ -0,0 +1,25 @@ +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/Exceptions.ts b/packages/idempotency/src/Exceptions.ts new file mode 100644 index 0000000000..405a59aa66 --- /dev/null +++ b/packages/idempotency/src/Exceptions.ts @@ -0,0 +1,17 @@ +class IdempotencyItemNotFoundError extends Error { + +} + +class IdempotencyItemAlreadyExistsError extends Error{ + +} + +class IdempotencyInvalidStatusError extends Error { + +} + +export { + IdempotencyItemNotFoundError, + IdempotencyItemAlreadyExistsError, + IdempotencyInvalidStatusError +}; \ No newline at end of file diff --git a/packages/idempotency/src/persistence/DynamoDbPersistenceLayer.ts b/packages/idempotency/src/persistence/DynamoDbPersistenceLayer.ts index 6592841b3f..97cc752533 100644 --- a/packages/idempotency/src/persistence/DynamoDbPersistenceLayer.ts +++ b/packages/idempotency/src/persistence/DynamoDbPersistenceLayer.ts @@ -1,18 +1,130 @@ -/* eslint-disable @typescript-eslint/no-empty-function */ -import { IdempotencyRecord, PersistenceLayer } from './PersistenceLayer'; +import { DynamoDB, DynamoDBServiceException } from '@aws-sdk/client-dynamodb'; +import { DynamoDBDocument, GetCommandOutput } from '@aws-sdk/lib-dynamodb'; +import { DynamoPersistenceConstructorOptions } from '../types/DynamoPersistenceConstructorOptions'; +import { IdempotencyItemAlreadyExistsError, IdempotencyItemNotFoundError } from '../Exceptions'; +import { IdempotencyRecordStatus } from '../types/IdempotencyRecordStatus'; +import { IdempotencyRecord } from './IdempotencyRecord'; +import { PersistenceLayer } from './PersistenceLayer'; class DynamoDBPersistenceLayer extends PersistenceLayer { - public constructor(_tableName: string, _key_attr: string = 'id') { + private dataAttr: string; + private expiryAttr: string; + private inProgressExpiryAttr: string; + private keyAttr: string; + private statusAttr: string; + private table: DynamoDBDocument | undefined; + private tableName: string; + + public constructor(constructorOptions: DynamoPersistenceConstructorOptions) { super(); + + this.tableName = constructorOptions.tableName; + this.keyAttr = constructorOptions.keyAttr ?? 'id'; + this.statusAttr = constructorOptions.statusAttr ?? 'status'; + this.expiryAttr = constructorOptions.expiryAttr ?? 'expiration'; + this.inProgressExpiryAttr = constructorOptions.inProgressExpiryAttr ?? 'in_progress_expiry_attr'; + this.dataAttr = constructorOptions.data_attr ?? 'data'; + } + + protected async _deleteRecord(record: IdempotencyRecord): Promise { + const table: DynamoDBDocument = this.getTable(); + await table.delete({ + TableName: this.tableName, Key: { [this.keyAttr]: record.idempotencyKey } + }); + } + + protected async _getRecord(idempotencyKey: string): Promise { + const table: DynamoDBDocument = this.getTable(); + const output: GetCommandOutput = await table.get( + { + TableName: this.tableName, Key: { + [this.keyAttr]: idempotencyKey + }, + ConsistentRead: true + } + ); + + if (!output.Item) { + throw new IdempotencyItemNotFoundError(); + } + + return new IdempotencyRecord({ + idempotencyKey: output.Item[this.keyAttr], + status: output.Item[this.statusAttr], + expiryTimestamp: output.Item[this.expiryAttr], + inProgressExpiryTimestamp: output.Item[this.inProgressExpiryAttr], + responseData: output.Item[this.dataAttr] + }); + } + + protected async _putRecord(_record: IdempotencyRecord): Promise { + const table: DynamoDBDocument = this.getTable(); + + const item = { + [this.keyAttr]: _record.idempotencyKey, + [this.expiryAttr]: _record.expiryTimestamp, + [this.statusAttr]: _record.getStatus() + }; + + const idempotencyKeyDoesNotExist = 'attribute_not_exists(#id)'; + const idempotencyKeyExpired = '#expiry < :now'; + const notInProgress = 'NOT #status = :inprogress'; + const conditionalExpression = `${idempotencyKeyDoesNotExist} OR ${idempotencyKeyExpired} OR ${notInProgress}`; + try { + await table.put({ + TableName: this.tableName, + Item: item, + ExpressionAttributeNames: { + '#id': this.keyAttr, + '#expiry': this.expiryAttr, + '#status': this.statusAttr + }, + ExpressionAttributeValues: { + ':now': Date.now() / 1000, + ':inprogress': IdempotencyRecordStatus.INPROGRESS + }, + ConditionExpression: conditionalExpression + } + ); + } catch (e){ + if ((e as DynamoDBServiceException).name === 'ConditionalCheckFailedException'){ + throw new IdempotencyItemAlreadyExistsError(); + } + + throw e; + } } - protected async _deleteRecord(): Promise {} - protected async _getRecord(): Promise { - return Promise.resolve({} as IdempotencyRecord); + + protected async _updateRecord(record: IdempotencyRecord): Promise { + const table: DynamoDBDocument = this.getTable(); + await table.update( + { + TableName: this.tableName, + Key: { + [this.keyAttr]: record.idempotencyKey + }, + UpdateExpression: 'SET #status = :status, #expiry = :expiry', + ExpressionAttributeNames: { + '#status': this.statusAttr, + '#expiry': this.expiryAttr + }, + ExpressionAttributeValues: { + ':status': record.getStatus(), + ':expiry': record.expiryTimestamp + } + } + ); + } + + private getTable(): DynamoDBDocument { + if (!this.table) + this.table = DynamoDBDocument.from(new DynamoDB({}), { marshallOptions: { removeUndefinedValues: true } }); + + return this.table; } - protected async _putRecord(_record: IdempotencyRecord): Promise {} - protected async _updateRecord(): Promise {} } export { DynamoDBPersistenceLayer -}; \ No newline at end of file +}; + diff --git a/packages/idempotency/src/persistence/IdempotencyRecord.ts b/packages/idempotency/src/persistence/IdempotencyRecord.ts index 7f8fac70ec..b512cc5786 100644 --- a/packages/idempotency/src/persistence/IdempotencyRecord.ts +++ b/packages/idempotency/src/persistence/IdempotencyRecord.ts @@ -1,25 +1,41 @@ -import { IdempotencyRecordStatus } from 'types/IdempotencyRecordStatus'; +import { IdempotencyRecordOptions } from 'types/IdempotencyRecordOptions'; +import { IdempotencyInvalidStatusError } from '../Exceptions'; +import { IdempotencyRecordStatus } from '../types/IdempotencyRecordStatus'; class IdempotencyRecord { + public expiryTimestamp: number | undefined; + public idempotencyKey: string; + public inProgressExpiryTimestamp: number | undefined; + public payloadHash: string | undefined; + public responseData: Record | undefined; + private status: IdempotencyRecordStatus; + + public constructor(constructorOptions: IdempotencyRecordOptions) { + this.idempotencyKey = constructorOptions.idempotencyKey; + this.expiryTimestamp = constructorOptions.expiryTimestamp; + this.inProgressExpiryTimestamp = constructorOptions.inProgressExpiryTimestamp; + this.responseData = constructorOptions.responseData; + this.payloadHash = constructorOptions.payloadHash; + this.status = constructorOptions.status; + } + + public getResponse(): Record | undefined { + return this.responseData; + } - public constructor(public idempotencyKey: string, - private status: IdempotencyRecordStatus, - public expiryTimestamp: number | undefined, - public inProgressExpiryTimestamp: number | undefined, - public responseData: string |undefined, - public payloadHash: string | undefined) {} - public getStatus(): IdempotencyRecordStatus { - return IdempotencyRecordStatus.INPROGRESS; + if (this.isExpired()) { + return IdempotencyRecordStatus.EXPIRED; + } else if (Object.values(IdempotencyRecordStatus).includes(this.status)) { + return this.status; + } else { + throw new IdempotencyInvalidStatusError(); + } } - - public isExpired(): boolean { - return false; + + private isExpired(): boolean { + return this.expiryTimestamp !== undefined && ((Date.now() / 1000) > this.expiryTimestamp); } - - public responseJsonAsObject(): Record | undefined { - return; - } } export { diff --git a/packages/idempotency/src/persistence/PersistenceLayer.ts b/packages/idempotency/src/persistence/PersistenceLayer.ts index 1cd2c54411..d64c3d1546 100644 --- a/packages/idempotency/src/persistence/PersistenceLayer.ts +++ b/packages/idempotency/src/persistence/PersistenceLayer.ts @@ -1,24 +1,154 @@ -/* eslint-disable @typescript-eslint/no-empty-function */ +import { BinaryToTextEncoding, createHash, Hash } from 'crypto'; +import { IdempotencyRecordStatus } from '../types/IdempotencyRecordStatus'; +import { EnvironmentVariablesService } from '../EnvironmentVariablesService'; import { IdempotencyRecord } from './IdempotencyRecord'; import { PersistenceLayerInterface } from './PersistenceLayerInterface'; abstract class PersistenceLayer implements PersistenceLayerInterface { - public constructor() { } - public configure(_functionName: string = ''): void {} - public async deleteRecord(): Promise { } - public async getRecord(): Promise { - return Promise.resolve({} as IdempotencyRecord); + + // envVarsService is always initialized in the constructor + private envVarsService!: EnvironmentVariablesService; + + private expiresAfterSeconds: number; + + private functionName: string = ''; + + private hashDigest: BinaryToTextEncoding; + + private hashFunction: string; + + public constructor() { + this.setEnvVarsService(); + this.expiresAfterSeconds = 60 * 60; //one hour is the default expiration + this.hashFunction = 'md5'; + this.hashDigest = 'base64'; + } - public async saveInProgress(): Promise { } - public async saveSuccess(): Promise { } + public configure(functionName: string = ''): void { + this.functionName = this.getEnvVarsService().getLambdaFunctionName() + '.' + functionName; + } + + /** + * Deletes a record from the persistence store for the persistence key generated from the data passed in. + * + * @param data - the data payload that will be hashed to create the hash portion of the idempotency key + */ + public async deleteRecord(data: unknown): Promise { + const idempotencyRecord: IdempotencyRecord = new IdempotencyRecord({ + idempotencyKey: this.getHashedIdempotencyKey(data), + status: IdempotencyRecordStatus.EXPIRED + }); + + this._deleteRecord(idempotencyRecord); + } + /** + * Retrieves idempotency key for the provided data and fetches data for that key from the persistence store + * + * @param data - the data payload that will be hashed to create the hash portion of the idempotency key + */ + public async getRecord(data: unknown): Promise { + const idempotencyKey: string = this.getHashedIdempotencyKey(data); + + return this._getRecord(idempotencyKey); + } + + /** + * Saves a record indicating that the function's execution is currently in progress + * + * @param data - the data payload that will be hashed to create the hash portion of the idempotency key + */ + public async saveInProgress(data: unknown): Promise { + const idempotencyRecord: IdempotencyRecord = + new IdempotencyRecord({ + idempotencyKey: this.getHashedIdempotencyKey(data), + status: IdempotencyRecordStatus.INPROGRESS, + expiryTimestamp: this.getExpiryTimestamp() + }); + + return this._putRecord(idempotencyRecord); + } + + /** + * Saves a record of the function completing successfully. This will create a record with a COMPLETED status + * and will save the result of the completed function in the idempotency record. + * + * @param data - the data payload that will be hashed to create the hash portion of the idempotency key + * @param result - the result of the successfully completed function + */ + public async saveSuccess(data: unknown, result: Record): Promise { + const idempotencyRecord: IdempotencyRecord = + new IdempotencyRecord({ + idempotencyKey: this.getHashedIdempotencyKey(data), + status: IdempotencyRecordStatus.COMPLETED, + expiryTimestamp: this.getExpiryTimestamp(), + responseData: result + }); - protected abstract _deleteRecord(): Promise; - protected abstract _getRecord(): Promise; + this._updateRecord(idempotencyRecord); + + } + + protected abstract _deleteRecord(record: IdempotencyRecord): Promise; + protected abstract _getRecord(idempotencyKey: string): Promise; protected abstract _putRecord(record: IdempotencyRecord): Promise; - protected abstract _updateRecord(): Promise; + protected abstract _updateRecord(record: IdempotencyRecord): Promise; + + /** + * Generates a hash of the data and returns the digest of that hash + * + * @param data the data payload that will generate the hash + * @returns the digest of the generated hash + */ + private generateHash(data: string): string{ + const hash: Hash = createHash(this.hashFunction); + hash.update(data); + + return hash.digest(this.hashDigest); + } + + /** + * Getter for `envVarsService`. + * Used internally during initialization. + */ + private getEnvVarsService(): EnvironmentVariablesService { + return this.envVarsService; + } + + /** + * Creates the expiry timestamp for the idempotency record + * + * @returns the expiry time for the record expressed as number of seconds past the UNIX epoch + */ + private getExpiryTimestamp(): number { + const currentTime: number = Date.now() / 1000; + + return currentTime + this.expiresAfterSeconds; + } + + /** + * Generates the idempotency key used to identify records in the persistence store. + * + * @param data the data payload that will be hashed to create the hash portion of the idempotency key + * @returns the idempotency key + */ + private getHashedIdempotencyKey(data: unknown): string { + if (!data){ + console.warn('No data found for idempotency key'); + } + + return this.functionName + '#' + this.generateHash(JSON.stringify(data)); + } + + /** + * Setter and initializer for `envVarsService`. + * Used internally during initialization. + */ + private setEnvVarsService(): void { + this.envVarsService = new EnvironmentVariablesService(); + } + } export { - IdempotencyRecord, PersistenceLayer }; \ No newline at end of file diff --git a/packages/idempotency/src/persistence/PersistenceLayerInterface.ts b/packages/idempotency/src/persistence/PersistenceLayerInterface.ts index 4b2da46b38..e6bce97fde 100644 --- a/packages/idempotency/src/persistence/PersistenceLayerInterface.ts +++ b/packages/idempotency/src/persistence/PersistenceLayerInterface.ts @@ -1,11 +1,11 @@ -import { IdempotencyRecord } from './PersistenceLayer'; +import { IdempotencyRecord } from './IdempotencyRecord'; interface PersistenceLayerInterface { configure(functionName: string): void - saveInProgress(): Promise - saveSuccess(): Promise - deleteRecord(): Promise - getRecord(): Promise + saveInProgress(data: unknown): Promise + saveSuccess(data: unknown, result: unknown): Promise + deleteRecord(data: unknown): Promise + getRecord(data: unknown): Promise } export { PersistenceLayerInterface }; diff --git a/packages/idempotency/src/persistence/index.ts b/packages/idempotency/src/persistence/index.ts new file mode 100644 index 0000000000..7256fa4e7b --- /dev/null +++ b/packages/idempotency/src/persistence/index.ts @@ -0,0 +1,4 @@ +export * from './DynamoDbPersistenceLayer'; +export * from './PersistenceLayer'; +export * from './PersistenceLayerInterface'; +export * from './IdempotencyRecord'; \ No newline at end of file diff --git a/packages/idempotency/src/types/DynamoPersistenceConstructorOptions.ts b/packages/idempotency/src/types/DynamoPersistenceConstructorOptions.ts new file mode 100644 index 0000000000..c2308b362e --- /dev/null +++ b/packages/idempotency/src/types/DynamoPersistenceConstructorOptions.ts @@ -0,0 +1,12 @@ +type DynamoPersistenceConstructorOptions = { + tableName: string + keyAttr?: string + statusAttr?: string + expiryAttr?: string + inProgressExpiryAttr?: string + data_attr?: string +}; + +export { + DynamoPersistenceConstructorOptions +}; \ No newline at end of file diff --git a/packages/idempotency/src/types/IdempotencyRecordOptions.ts b/packages/idempotency/src/types/IdempotencyRecordOptions.ts new file mode 100644 index 0000000000..07c9b91bb3 --- /dev/null +++ b/packages/idempotency/src/types/IdempotencyRecordOptions.ts @@ -0,0 +1,14 @@ +import { IdempotencyRecordStatus } from './IdempotencyRecordStatus'; + +type IdempotencyRecordOptions = { + idempotencyKey: string + status: IdempotencyRecordStatus + expiryTimestamp?: number + inProgressExpiryTimestamp?: number + responseData?: Record + payloadHash?: string +}; + +export { + IdempotencyRecordOptions +}; \ No newline at end of file diff --git a/packages/idempotency/src/types/index.ts b/packages/idempotency/src/types/index.ts new file mode 100644 index 0000000000..850ccbd19c --- /dev/null +++ b/packages/idempotency/src/types/index.ts @@ -0,0 +1,2 @@ +export * from './AnyFunction'; +export * from './IdempotencyRecordStatus'; \ No newline at end of file diff --git a/packages/idempotency/tests/helpers/populateEnvironmentVariables.ts b/packages/idempotency/tests/helpers/populateEnvironmentVariables.ts new file mode 100644 index 0000000000..42b8feeb63 --- /dev/null +++ b/packages/idempotency/tests/helpers/populateEnvironmentVariables.ts @@ -0,0 +1,2 @@ +// Reserved variables +process.env.AWS_REGION = 'us-east-1'; diff --git a/packages/idempotency/tests/unit/EnvironmentVariableService.test.ts b/packages/idempotency/tests/unit/EnvironmentVariableService.test.ts new file mode 100644 index 0000000000..2480c328cb --- /dev/null +++ b/packages/idempotency/tests/unit/EnvironmentVariableService.test.ts @@ -0,0 +1,34 @@ +/** + * 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/persistence/DynamoDbPersistenceLayer.test.ts b/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts new file mode 100644 index 0000000000..8ca16818dd --- /dev/null +++ b/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts @@ -0,0 +1,282 @@ +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 { IdempotencyRecordStatus } from '../../../src/types/IdempotencyRecordStatus'; + +/** + * Test DynamoDBPersistenceLayer class + * + * @group unit/idempotency/all + */ + +describe('Class: DynamoDbPersistenceLayer', () => { + class TestDynamoPersistenceLayer extends DynamoDBPersistenceLayer { + public _deleteRecord(record: IdempotencyRecord): Promise { + return super._deleteRecord(record); + } + + public _getRecord(idempotencyKey: string): Promise { + return super._getRecord(idempotencyKey); + } + + public _putRecord(_record: IdempotencyRecord): Promise { + return super._putRecord(_record); + } + + public _updateRecord(record: IdempotencyRecord): Promise { + return super._updateRecord(record); + } + } + + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('Method: _putRecord', () => { + const currentDateInMilliseconds = 1000; + const currentDateInSeconds = 1; + + beforeEach(() => { + 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 }); + + const key = 'key'; + const status = IdempotencyRecordStatus.EXPIRED; + const expiryTimestamp = 0; + const inProgressExpiryTimestamp = 0; + const record = new IdempotencyRecord({ + idempotencyKey: key, + status, + expiryTimestamp, + inProgressExpiryTimestamp + }); + const dynamoClient = mockClient(DynamoDBDocument).on(PutCommand).resolves({}); + + // Act + await persistenceLayer._putRecord(record); + + // Assess + expect(dynamoClient).toReceiveCommandWith(PutCommand, { + TableName: tableName, + Item: { 'id': key, '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 status = IdempotencyRecordStatus.EXPIRED; + const expiryTimestamp = 0; + const inProgressExpiryTimestamp = 0; + const record = new IdempotencyRecord({ + idempotencyKey: key, + 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 + expect(dynamoClient).toReceiveCommandWith(PutCommand, { + TableName: tableName, + Item: { 'id': key, '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'; + const status = IdempotencyRecordStatus.EXPIRED; + const expiryTimestamp = 0; + const inProgressExpiryTimestamp = 0; + const record = new IdempotencyRecord({ + idempotencyKey: key, + 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 + expect(dynamoClient).toReceiveCommandWith(PutCommand, { + TableName: tableName, + Item: { 'id': key, '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'; + + const status = IdempotencyRecordStatus.INPROGRESS; + const expiryTimestamp = 10; + const inProgressExpiryTimestamp = 10; + const responseData = {}; + const dynamoClient = mockClient(DynamoDBDocument).on(GetCommand).resolves({ + Item: { + id: key, + status, + 'expiration': expiryTimestamp, + 'in_progress_expiry_attr': inProgressExpiryTimestamp, + data: responseData + } + }); + jest.spyOn(Date, 'now').mockReturnValue(0); + + // Act + const record: IdempotencyRecord = await persistenceLayer._getRecord(key); + + // Assess + expect(dynamoClient).toReceiveCommandWith(GetCommand, { + TableName: tableName, + Key: { + id: key + }, + ConsistentRead: true + }); + expect(record.getStatus()).toEqual(IdempotencyRecordStatus.INPROGRESS); + expect(record.idempotencyKey).toEqual(key); + 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'; + + 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 + expect(dynamoClient).toReceiveCommandWith(GetCommand, { + TableName: tableName, + Key: { + id: key + }, + 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'; + const status = IdempotencyRecordStatus.EXPIRED; + const expiryTimestamp = 0; + const inProgressExpiryTimestamp = 0; + const record = new IdempotencyRecord({ + idempotencyKey: key, + status, + expiryTimestamp, + inProgressExpiryTimestamp + }); + const dynamoClient = mockClient(DynamoDBDocument).on(UpdateCommand).resolves({}); + + // Act + await persistenceLayer._updateRecord(record); + + // Assess + expect(dynamoClient).toReceiveCommandWith(UpdateCommand, { + TableName: tableName, + Key: { id: key }, + 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'; + const status = IdempotencyRecordStatus.EXPIRED; + const expiryTimestamp = 0; + const inProgressExpiryTimestamp = 0; + const record = new IdempotencyRecord({ + idempotencyKey: key, + status, + expiryTimestamp, + inProgressExpiryTimestamp + }); + const dynamoClient = mockClient(DynamoDBDocument).on(DeleteCommand).resolves({}); + + // Act + await persistenceLayer._deleteRecord(record); + + // Assess + expect(dynamoClient).toReceiveCommandWith(DeleteCommand, { + TableName: tableName, + Key: { id: key } + }); + }); + }); +}); \ 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 new file mode 100644 index 0000000000..7f0c00db04 --- /dev/null +++ b/packages/idempotency/tests/unit/persistence/IdempotencyRecord.test.ts @@ -0,0 +1,97 @@ +import { IdempotencyInvalidStatusError } from '../../../src/Exceptions'; +import { IdempotencyRecord } from '../../../src/persistence/IdempotencyRecord'; +import { IdempotencyRecordStatus } from '../../../src/types/IdempotencyRecordStatus'; +/** + * Test IdempotencyRecord class + * + * @group unit/idempotency/all + */ +const mockIdempotencyKey = '123'; +const mockData = undefined; +const mockInProgressExpiry = 123; +const mockPayloadHash = '123'; + +describe('Given an INPROGRESS record that has already expired', () => { + let idempotencyRecord: IdempotencyRecord; + beforeEach(() => { + const mockNowAfterExpiryTime = 1487076708000; + const expiryTimeBeforeNow = 1487076707; + Date.now = jest.fn(() => mockNowAfterExpiryTime); + idempotencyRecord = new IdempotencyRecord({ + idempotencyKey: mockIdempotencyKey, + status: IdempotencyRecordStatus.INPROGRESS, + expiryTimestamp: expiryTimeBeforeNow, + inProgressExpiryTimestamp: mockInProgressExpiry, + responseData: mockData, + payloadHash: mockPayloadHash + }); + }); + describe('When checking the status of the idempotency record', () => { + let resultingStatus: IdempotencyRecordStatus; + beforeEach(() => { + resultingStatus = idempotencyRecord.getStatus(); + }); + + test('Then the status is EXPIRED', () => { + expect(resultingStatus).toEqual(IdempotencyRecordStatus.EXPIRED); + }); + }); +}); + +describe('Given an idempotency record that is not expired', () => { + let idempotencyRecord: IdempotencyRecord; + beforeEach(() => { + const mockNowBeforeExiryTime = 1487076707000; + const expiryTimeAfterNow = 1487076708; + Date.now = jest.fn(() => mockNowBeforeExiryTime); + idempotencyRecord = new IdempotencyRecord({ + idempotencyKey: mockIdempotencyKey, + status: IdempotencyRecordStatus.INPROGRESS, + expiryTimestamp: expiryTimeAfterNow, + inProgressExpiryTimestamp: mockInProgressExpiry, + responseData: mockData, + payloadHash: mockPayloadHash + }); + }); + describe('When checking the status of the idempotency record', () => { + test('Then the status is EXPIRED', () => { + expect(idempotencyRecord.getStatus()).toEqual(IdempotencyRecordStatus.INPROGRESS); + }); + + test('Then the record is returned', () => { + expect(idempotencyRecord.getResponse()).toEqual(mockData); + }); + }); +}); + +describe('Given an idempotency record that has a status not in the IdempotencyRecordStatus enum', () => { + let idempotencyRecord: IdempotencyRecord; + beforeEach(() => { + const mockNowBeforeExiryTime = 1487076707000; + const expiryTimeAfterNow = 1487076708; + Date.now = jest.fn(() => mockNowBeforeExiryTime); + idempotencyRecord = new IdempotencyRecord({ + idempotencyKey: mockIdempotencyKey, + status: 'NOT_A_STATUS' as IdempotencyRecordStatus, + expiryTimestamp: expiryTimeAfterNow, + inProgressExpiryTimestamp: mockInProgressExpiry, + responseData: mockData, + payloadHash: mockPayloadHash + }); + }); + describe('When checking the status of the idempotency record', () => { + let resultingError: Error; + beforeEach(() => { + try { + idempotencyRecord.getStatus(); + } catch (e: unknown) { + resultingError = e as Error; + } + + }); + + test('Then an IdempotencyInvalidStatusError is thrown ', () => { + expect(resultingError).toBeInstanceOf(IdempotencyInvalidStatusError); + }); + }); +}); \ No newline at end of file diff --git a/packages/idempotency/tests/unit/persistence/PersistenceLayer.test.ts b/packages/idempotency/tests/unit/persistence/PersistenceLayer.test.ts new file mode 100644 index 0000000000..ee899c3342 --- /dev/null +++ b/packages/idempotency/tests/unit/persistence/PersistenceLayer.test.ts @@ -0,0 +1,251 @@ +/** + * Test PersistenceLayer class + * + * @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'; + +jest.mock('crypto', () => ({ + createHash: jest.fn(), +})); + +const cryptoUpdateMock = jest.fn(); +const cryptoDigestMock = jest.fn(); +const mockDigest = 'hashDigest'; + +describe('Class: Persistence Layer', ()=> { + + const deleteRecord = jest.fn(); + const getRecord = jest.fn(); + const putRecord = jest.fn(); + const updateRecord = jest.fn(); + + class PersistenceLayerTestClass extends PersistenceLayer { + + protected _deleteRecord = deleteRecord; + + protected _getRecord = getRecord; + + protected _putRecord = putRecord; + + protected _updateRecord = updateRecord; + } + + describe('Method: saveInProgress', ()=> { + beforeEach(()=> { + putRecord.mockClear(); + (createHash as jest.MockedFunction).mockReturnValue( + { + update: cryptoUpdateMock, + digest: cryptoDigestMock.mockReturnValue(mockDigest) + } as unknown as Hash + ); + }); + + test('When called, it saves an IN_PROGRESS idempotency record via _putRecord()', async ()=> { + const data = 'someData'; + const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); + + await persistenceLayer.saveInProgress(data); + + 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); + + const functionName = 'functionName'; + + const expectedIdempotencyKey = lambdaFunctionName + '.' + functionName + '#' + mockDigest; + const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); + persistenceLayer.configure(functionName); + + await persistenceLayer.saveInProgress(data); + + 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') + ); + 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); + + const expectedIdempotencyKey = lambdaFunctionName + '.' + '#' + mockDigest; + const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); + persistenceLayer.configure(); + + await persistenceLayer.saveInProgress(data); + + 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') + ); + expect(savedIdempotencyRecord.idempotencyKey).toEqual(expectedIdempotencyKey); + }); + + test('When called, it sets the expiry timestamp to one hour in the future', async ()=> { + 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); + + 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'); + const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); + + await persistenceLayer.saveInProgress(''); + expect(consoleSpy).toHaveBeenCalled(); + }); + + }); + + describe('Method: saveSuccess', ()=> { + beforeEach(()=> { + updateRecord.mockClear(); + (createHash as jest.MockedFunction).mockReturnValue( + { + update: cryptoUpdateMock, + digest: cryptoDigestMock + } as unknown as Hash + ); + }); + + test('When called, it updates the idempotency record status to COMPLETED', async () => { + const data = 'someData'; + const result = {}; + const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); + + await persistenceLayer.saveSuccess(data, result); + + 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'; + + const expectedIdempotencyKey = lambdaFunctionName + '.' + functionName + '#' + mockDigest; + const persistenceLayer: PersistenceLayer = new PersistenceLayerTestClass(); + persistenceLayer.configure(functionName); + + await persistenceLayer.saveSuccess(data, result); + + const savedIdempotencyRecord: IdempotencyRecord = updateRecord.mock.calls[0][0]; + + expect(createHash).toHaveBeenCalledWith( + expect.stringMatching('md5'), + ); + expect(cryptoUpdateMock).toHaveBeenCalledWith(expect.stringMatching(data)); + 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 ()=> { + 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); + + const savedIdempotencyRecord: IdempotencyRecord = updateRecord.mock.calls[0][0]; + expect(savedIdempotencyRecord.expiryTimestamp).toEqual(currentSeconds + oneHourSeconds); + + }); + + }); + + describe('Method: getRecord', ()=> { + beforeEach(()=> { + putRecord.mockClear(); + (createHash as jest.MockedFunction).mockReturnValue( + { + update: cryptoUpdateMock, + digest: cryptoDigestMock.mockReturnValue(mockDigest) + } 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); + + persistenceLayer.getRecord(data); + + expect(getRecord).toHaveBeenCalledWith(expectedIdempotencyKey); + }); + }); + + describe('Method: deleteRecord', ()=> { + beforeEach(()=> { + putRecord.mockClear(); + (createHash as jest.MockedFunction).mockReturnValue( + { + update: cryptoUpdateMock, + digest: cryptoDigestMock.mockReturnValue(mockDigest) + } as unknown as Hash + ); + }); + + 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); + + const functionName = 'functionName'; + const expectedIdempotencyKey = lambdaFunctionName + '.' + functionName + '#' + mockDigest; + persistenceLayer.configure(functionName); + + persistenceLayer.deleteRecord(data); + const deletedIdempotencyRecord: IdempotencyRecord = deleteRecord.mock.calls[0][0]; + + expect(deletedIdempotencyRecord.idempotencyKey).toEqual(expectedIdempotencyKey); + }); + }); +}); \ No newline at end of file