diff --git a/package-lock.json b/package-lock.json index e63710ab3..830374ca3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,8 @@ "dependencies": { "@aws-sdk/client-dynamodb": "^3.665.0", "@aws-sdk/lib-dynamodb": "^3.665.0", - "@smithy/shared-ini-file-loader": "^3.1.8" + "@smithy/shared-ini-file-loader": "^3.1.8", + "aws-sdk-client-mock-jest": "^4.1.0" }, "devDependencies": { "@babel/core": "^7.17.2", @@ -819,7 +820,6 @@ "version": "7.23.4", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.4.tgz", "integrity": "sha512-r1IONyb6Ia+jYR2vvIDhdWdlTGhqbBoFqLTQidzZ4kepUFH15ejXvFHxCVbtl7BOXIudsIubf4E81xeA3h3IXA==", - "dev": true, "dependencies": { "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" @@ -1177,7 +1177,6 @@ "version": "7.22.20", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -1223,7 +1222,6 @@ "version": "7.23.4", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", - "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", @@ -3159,6 +3157,27 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils/node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/@jest/fake-timers": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", @@ -3304,6 +3323,18 @@ "node": ">=8" } }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/@jest/source-map": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", @@ -7182,6 +7213,12 @@ "integrity": "sha512-l5qumKFWU0S+4ZzMaLXFU8tQZsicHEMEyAxI5kDFGhJsRqDwe0a7/iPA/GdxlGyDKseQQAgIz5kzU7eXTrlSpA==", "dev": true }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "license": "MIT" + }, "node_modules/@sinonjs/commons": { "version": "1.8.6", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", @@ -7204,7 +7241,6 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.2.tgz", "integrity": "sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.1", @@ -7216,7 +7252,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" @@ -7226,7 +7261,6 @@ "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, "license": "MIT", "engines": { "node": ">=4" @@ -7236,7 +7270,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -7246,7 +7279,6 @@ "version": "0.7.3", "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", - "dev": true, "license": "(Unlicense OR Apache-2.0)" }, "node_modules/@smithy/abort-controller": { @@ -7931,14 +7963,12 @@ "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" }, "node_modules/@types/istanbul-lib-report": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", - "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "*" } @@ -7947,7 +7977,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", - "dev": true, "dependencies": { "@types/istanbul-lib-report": "*" } @@ -7990,7 +8019,6 @@ "version": "20.9.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.3.tgz", "integrity": "sha512-nk5wXLAXGBKfrhLB0cyHGbSqopS+nz0BUgZkUQqSHSSgdee0kssp1IAqlQOu333bW+gMNs2QREx7iynm19Abxw==", - "dev": true, "dependencies": { "undici-types": "~5.26.4" } @@ -8017,7 +8045,6 @@ "version": "17.0.3", "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.3.tgz", "integrity": "sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw==", - "dev": true, "license": "MIT", "dependencies": { "@types/sinonjs__fake-timers": "*" @@ -8027,14 +8054,12 @@ "version": "8.1.5", "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", - "dev": true, "license": "MIT" }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "dev": true + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==" }, "node_modules/@types/unist": { "version": "2.0.10", @@ -8054,8 +8079,7 @@ "node_modules/@types/yargs-parser": { "version": "21.0.3", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" }, "node_modules/@typescript-eslint/types": { "version": "4.28.2", @@ -8182,6 +8206,59 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "node_modules/@vitest/expect": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.5.tgz", + "integrity": "sha512-nZSBTW1XIdpZvEJyoP/Sy8fUg0b8od7ZpGDkTUcfJ7wz/VoZAFzFfLyxVxGFhUjJzhYqSbIpfMtl/+k/dpWa3Q==", + "license": "MIT", + "dependencies": { + "@vitest/spy": "2.1.5", + "@vitest/utils": "2.1.5", + "chai": "^5.1.2", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.5.tgz", + "integrity": "sha512-4ZOwtk2bqG5Y6xRGHcveZVr+6txkH7M2e+nPFd6guSoN638v/1XQ0K06eOpi0ptVU/2tW/pIU4IoPotY/GZ9fw==", + "license": "MIT", + "dependencies": { + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.5.tgz", + "integrity": "sha512-aWZF3P0r3w6DiYTVskOYuhBc7EMc3jvn1TkBg8ttylFFRqNN2XGD7V5a4aQdk6QiUzZQ4klNBSpCLJgWNdIiNw==", + "license": "MIT", + "dependencies": { + "tinyspy": "^3.0.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.5.tgz", + "integrity": "sha512-yfj6Yrp0Vesw2cwJbP+cl04OC+IHFsuQsrsJBL9pyGeQXE56v1UAOQco+SR55Vf1nQzfV0QJg1Qum7AaWUwwYg==", + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.5", + "loupe": "^3.1.2", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", @@ -8401,7 +8478,6 @@ "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" }, @@ -8591,6 +8667,15 @@ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", "dev": true }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -8660,7 +8745,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/aws-sdk-client-mock/-/aws-sdk-client-mock-4.1.0.tgz", "integrity": "sha512-h/tOYTkXEsAcV3//6C1/7U4ifSpKyJvb6auveAepqqNJl6TdZaPFEtKjBQNf8UxQdDP850knB2i/whq4zlsxJw==", - "dev": true, "license": "MIT", "dependencies": { "@types/sinon": "^17.0.3", @@ -8668,6 +8752,255 @@ "tslib": "^2.1.0" } }, + "node_modules/aws-sdk-client-mock-jest": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/aws-sdk-client-mock-jest/-/aws-sdk-client-mock-jest-4.1.0.tgz", + "integrity": "sha512-+g4a5Hp+MmPqqNnvwfLitByggrqf+xSbk1pm6fBYHNcon6+aQjL5iB+3YB6HuGPemY+/mUKN34iP62S14R61bA==", + "license": "MIT", + "dependencies": { + "@vitest/expect": ">1.6.0", + "expect": ">28.1.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "aws-sdk-client-mock": "4.1.0", + "vitest": ">1.6.0" + }, + "peerDependenciesMeta": { + "vitest": { + "optional": true + } + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/aws-sdk-client-mock-jest/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==", + "license": "MIT", + "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-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "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/aws-sdk-client-mock-jest/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==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/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==", + "license": "MIT" + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/aws-sdk-client-mock-jest/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==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/aws-sdk-client-mock-jest/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/aws-sdk-client-mock-jest/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==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/aws-sdk-mock": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/aws-sdk-mock/-/aws-sdk-mock-6.2.0.tgz", @@ -9057,7 +9390,6 @@ "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" }, @@ -9298,11 +9630,26 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/chai": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz", + "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==", + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "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", @@ -9357,6 +9704,15 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, "node_modules/chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", @@ -9370,7 +9726,6 @@ "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, "funding": [ { "type": "github", @@ -9643,7 +9998,6 @@ "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" } @@ -9651,8 +10005,7 @@ "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 + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/color-support": { "version": "1.1.3", @@ -10086,6 +10439,15 @@ "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", "dev": true }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -10589,7 +10951,6 @@ "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" } @@ -11551,7 +11912,6 @@ "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" }, @@ -12127,8 +12487,7 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/graphemer": { "version": "1.4.0", @@ -12197,7 +12556,6 @@ "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" } @@ -13184,7 +13542,6 @@ "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" } @@ -15531,8 +15888,7 @@ "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 + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { "version": "3.14.1", @@ -15771,7 +16127,6 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", - "dev": true, "license": "MIT" }, "node_modules/keyv": { @@ -16821,7 +17176,6 @@ "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, "license": "MIT" }, "node_modules/lodash.ismatch": { @@ -17022,6 +17376,12 @@ "loose-envify": "cli.js" } }, + "node_modules/loupe": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", + "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", + "license": "MIT" + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -17418,7 +17778,6 @@ "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" @@ -17772,7 +18131,6 @@ "version": "6.1.1", "resolved": "https://registry.npmjs.org/nise/-/nise-6.1.1.tgz", "integrity": "sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.1", @@ -17786,7 +18144,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" @@ -17796,7 +18153,6 @@ "version": "13.0.2", "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.2.tgz", "integrity": "sha512-4Bb+oqXZTSTZ1q27Izly9lv8B9dlV61CROxPiVtywwzv5SnytJqhvYe6FclHYuXml4cd1VHPo1zd5PmTeJozvA==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.1" @@ -19918,7 +20274,6 @@ "version": "8.2.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=16" @@ -19933,6 +20288,15 @@ "node": ">=8" } }, + "node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -19943,7 +20307,6 @@ "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" }, @@ -21928,7 +22291,6 @@ "version": "18.0.1", "resolved": "https://registry.npmjs.org/sinon/-/sinon-18.0.1.tgz", "integrity": "sha512-a2N2TDY1uGviajJ6r4D1CyRAkzE9NNVlYOV1wX5xQDuAk0ONgzgRl0EjCQuRCPxOwp13ghsMwt9Gdldujs39qw==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.1", @@ -21947,7 +22309,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" @@ -21957,7 +22318,6 @@ "version": "11.2.2", "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.0" @@ -21967,7 +22327,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" @@ -21977,7 +22336,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -21987,7 +22345,6 @@ "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, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -22006,7 +22363,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, "engines": { "node": ">=8" } @@ -22223,7 +22579,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, "dependencies": { "escape-string-regexp": "^2.0.0" }, @@ -22235,7 +22590,6 @@ "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" } @@ -22755,7 +23109,6 @@ "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" }, @@ -23047,6 +23400,24 @@ "readable-stream": "3" } }, + "node_modules/tinyrainbow": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -23078,7 +23449,6 @@ "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" }, @@ -23242,7 +23612,6 @@ "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" } @@ -23383,8 +23752,7 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/unherit": { "version": "1.1.3", diff --git a/package.json b/package.json index 6e76a159f..0be2bb233 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,7 @@ "dependencies": { "@aws-sdk/client-dynamodb": "^3.665.0", "@aws-sdk/lib-dynamodb": "^3.665.0", - "@smithy/shared-ini-file-loader": "^3.1.8" + "@smithy/shared-ini-file-loader": "^3.1.8", + "aws-sdk-client-mock-jest": "^4.1.0" } } diff --git a/packages/sales-api-service/src/services/transactions/__tests__/finalise-transaction.spec.js b/packages/sales-api-service/src/services/transactions/__tests__/finalise-transaction.spec.js index 0b86f2f8a..6cb4f43bf 100644 --- a/packages/sales-api-service/src/services/transactions/__tests__/finalise-transaction.spec.js +++ b/packages/sales-api-service/src/services/transactions/__tests__/finalise-transaction.spec.js @@ -9,9 +9,11 @@ import { import { TRANSACTION_STAGING_TABLE, TRANSACTION_QUEUE } from '../../../config.js' import BusinessRulesLib from '@defra-fish/business-rules-lib' import moment from 'moment' -import AwsMock from 'aws-sdk' import { TRANSACTION_STATUS } from '../constants.js' import permissionsService from '../../permissions.service.js' +import { docClient } from '../../../../../connectors-lib/src/aws.js' +import { sqs } from '@defra-fish/connectors-lib' +import { UpdateCommand, GetCommand } from '@aws-sdk/lib-dynamodb' const { START_AFTER_PAYMENT_MINUTES } = BusinessRulesLib @@ -29,6 +31,19 @@ jest.mock('@defra-fish/business-rules-lib', () => ({ START_AFTER_PAYMENT_MINUTES: 30 })) +jest.mock('../../../../../connectors-lib/src/aws.js', () => ({ + docClient: { + send: jest.fn(), + createUpdateExpression: jest.fn() + } +})) + +jest.mock('@defra-fish/connectors-lib', () => ({ + sqs: { + sendMessage: jest.fn() + } +})) + const getStagedTransactionRecord = () => { const record = mockStagedTransactionRecord() const { @@ -44,10 +59,55 @@ describe('transaction service', () => { TRANSACTION_STAGING_TABLE.TableName = 'TestTable' TRANSACTION_QUEUE.Url = 'TestQueueUrl' }) - beforeEach(AwsMock.__resetAll) + + beforeEach(() => { + jest.clearAllMocks() + }) describe('finaliseTransaction', () => { - beforeEach(jest.clearAllMocks) + beforeEach(() => { + jest.clearAllMocks() + }) + + // helper function - GetCommand + const expectDynamoDbGet = mockRecord => { + expect(docClient.send).toHaveBeenCalledWith(expect.any(GetCommand)) + const getCommandInstance = docClient.send.mock.calls[0][0] + expect(getCommandInstance).toBeInstanceOf(GetCommand) + expect(getCommandInstance.input).toEqual({ + TableName: TRANSACTION_STAGING_TABLE.TableName, + Key: { id: mockRecord.id }, + ConsistentRead: true + }) + } + + // helper function - UpdateCommand + const expectDynamoDbUpdate = (mockRecord, completionFields) => { + expect(docClient.send).toHaveBeenCalledWith(expect.any(UpdateCommand)) + const updateCommandInstance = docClient.send.mock.calls[1][0] + expect(updateCommandInstance).toBeInstanceOf(UpdateCommand) + expect(updateCommandInstance.input).toEqual({ + TableName: TRANSACTION_STAGING_TABLE.TableName, + Key: { id: mockRecord.id }, + ...docClient.createUpdateExpression({ + ...completionFields, + permissions: mockRecord.permissions.map(p => ({ + ...p, + issueDate: p.issueDate ?? completionFields.payment.timestamp, + startDate: p.startDate ?? moment(completionFields.payment.timestamp).add(START_AFTER_PAYMENT_MINUTES, 'minutes').toISOString(), + endDate: expect.any(String), + referenceNumber: expect.any(String), + licensee: { + ...p.licensee, + obfuscatedDob: expect.any(String) + } + })), + status: { id: TRANSACTION_STATUS.FINALISED } + }), + ReturnValues: 'ALL_NEW' + }) + } + it.each([ ['records with a predetermined issue and start date', getStagedTransactionRecord], [ @@ -68,44 +128,26 @@ describe('transaction service', () => { method: 'Debit card' } } - AwsMock.DynamoDB.DocumentClient.__setResponse('get', { Item: mockRecord }) - AwsMock.DynamoDB.DocumentClient.__setResponse('update', { + + docClient.send.mockResolvedValueOnce({ Item: mockRecord }) + docClient.send.mockResolvedValueOnce({ Attributes: { ...mockRecord, ...completionFields, status: { id: TRANSACTION_STATUS.FINALISED } } }) - AwsMock.SQS.__setResponse('sendMessage', { MessageId: 'Test_Message' }) + sqs.sendMessage.mockResolvedValueOnce({ MessageId: 'Test_Message' }) const result = await finaliseTransaction({ id: mockRecord.id, ...completionFields }) + expect(result).toEqual({ ...mockRecord, ...completionFields, status: { id: TRANSACTION_STATUS.FINALISED, messageId: 'Test_Message' } }) - expect(AwsMock.DynamoDB.DocumentClient.mockedMethods.update).toBeCalledWith({ - TableName: TRANSACTION_STAGING_TABLE.TableName, - Key: { id: mockRecord.id }, - UpdateExpression: 'SET #payment = :payment,#permissions = :permissions,#status = :status', - ExpressionAttributeNames: { - '#payment': 'payment', - '#permissions': 'permissions', - '#status': 'status' - }, - ExpressionAttributeValues: { - ':payment': completionFields.payment, - ':permissions': mockRecord.permissions.map(p => ({ - ...p, - issueDate: p.issueDate ?? completionFields.payment.timestamp, - startDate: p.startDate ?? moment(completionFields.payment.timestamp).add(START_AFTER_PAYMENT_MINUTES, 'minutes').toISOString(), - endDate: expect.any(String), - referenceNumber: expect.any(String) - })), - ':status': { - id: TRANSACTION_STATUS.FINALISED - } - }, - ReturnValues: 'ALL_NEW' - }) - expect(AwsMock.SQS.mockedMethods.sendMessage).toBeCalledWith( + expect(docClient.send).toHaveBeenCalledTimes(2) + expectDynamoDbGet(mockRecord) + expectDynamoDbUpdate(mockRecord, completionFields) + + expect(sqs.sendMessage).toHaveBeenCalledWith( expect.objectContaining({ QueueUrl: TRANSACTION_QUEUE.Url, MessageGroupId: mockRecord.id, @@ -117,7 +159,7 @@ describe('transaction service', () => { it('throws 410 Gone if the transaction has already been finalised (and not yet staged into Dynamics)', async () => { const recordData = { status: { id: 'FINALISED' } } - AwsMock.DynamoDB.DocumentClient.__setResponse('get', { Item: recordData }) + docClient.send.mockResolvedValueOnce({ Item: recordData }) try { await finaliseTransaction({ id: 'already_finalised' }) } catch (e) { @@ -130,8 +172,8 @@ describe('transaction service', () => { it('throws 410 Gone if the transaction has already been finalised (and staged into Dynamics)', async () => { const recordData = { status: { id: 'FINALISED' } } // See retrieve-transaction.js - 1st response is null on the transaction table, 2nd response is the record from the transaction history table - AwsMock.DynamoDB.DocumentClient.__setNextResponses('get', { Item: null }, { Item: recordData }) - + docClient.send.mockResolvedValueOnce({ Item: null }) + docClient.send.mockResolvedValueOnce({ Item: recordData }) try { await finaliseTransaction({ id: 'already_finalised' }) } catch (e) { @@ -142,7 +184,7 @@ describe('transaction service', () => { }) it('throws 404 not found error if a record cannot be found for the given id', async () => { - AwsMock.DynamoDB.DocumentClient.__setResponse('get', { Item: undefined }) + docClient.send.mockResolvedValueOnce({ Item: undefined }) try { await finaliseTransaction({ id: 'not_found' }) } catch (e) { @@ -153,7 +195,7 @@ describe('transaction service', () => { it('throws 402 Payment Required error if the payment amount does not match the cost', async () => { const mockRecord = mockStagedTransactionRecord() - AwsMock.DynamoDB.DocumentClient.__setResponse('get', { Item: mockRecord }) + docClient.send.mockResolvedValueOnce({ Item: mockRecord }) try { const payload = { payment: { @@ -170,9 +212,9 @@ describe('transaction service', () => { } }) - it('throws 409 Conflict error if a recurring payment instruction was supplied but the transaciton does not support this', async () => { - const mockRecord = Object.assign(mockStagedTransactionRecord(), { isRecurringPaymentSupported: false }) - AwsMock.DynamoDB.DocumentClient.__setResponse('get', { Item: mockRecord }) + it('throws 409 Conflict error if a recurring payment instruction was supplied but the transaction does not support this', async () => { + const mockRecord = { ...mockStagedTransactionRecord(), isRecurringPaymentSupported: false } + docClient.send.mockResolvedValueOnce({ Item: mockRecord }) try { const payload = { payment: { @@ -211,7 +253,7 @@ describe('transaction service', () => { }) it('throws exceptions back up the stack', async () => { - AwsMock.DynamoDB.DocumentClient.__throwWithErrorOn('get') + docClient.send.mockRejectedValueOnce(new Error('Test error')) await expect(finaliseTransaction(mockTransactionPayload())).rejects.toThrow('Test error') }) }) @@ -219,10 +261,27 @@ describe('transaction service', () => { describe('finaliseTransaction adjusts licence times according to issue date and start date', () => { beforeEach(() => { BusinessRulesLib.START_AFTER_PAYMENT_MINUTES = 30 - AwsMock.SQS.__setResponse('sendMessage', { MessageId: 'Test_Message' }) jest.clearAllMocks() }) + const mockCreateUpdateExpression = (completionFields, updatedPermissions) => { + docClient.createUpdateExpression.mockReturnValue({ + UpdateExpression: 'SET #payment = :payment, #permissions = :permissions, #status = :status', + ExpressionAttributeNames: { + '#payment': 'payment', + '#permissions': 'permissions', + '#status': 'status' + }, + ExpressionAttributeValues: { + ':payment': completionFields.payment, + ':permissions': updatedPermissions, + ':status': { + id: TRANSACTION_STATUS.FINALISED + } + } + }) + } + it.each([ ['2021-09-30T17:14:01.892Z', '2021-09-30T17:14:01.892Z', '2022-09-30T17:14:01.892Z', 22, 'Web Sales'], ['2021-09-30T23:14:01.892Z', '2021-09-30T23:00:49.892Z', '2022-09-30T23:00:49.892Z', 38, 'Web Sales'], @@ -240,23 +299,42 @@ describe('transaction service', () => { mockPermission.startDate = startDate mockPermission.endDate = endDate const completionFields = getCompletionFields() - AwsMock.DynamoDB.DocumentClient.__setResponse('update', { - Attributes: { ...mockRecord, ...completionFields, status: { id: TRANSACTION_STATUS.FINALISED } } + + const expectedPermissions = mockRecord.permissions.map(p => ({ + ...p, + issueDate: p.issueDate ?? completionFields.payment.timestamp, + startDate: moment(issueDate).add(startAfterPaymentMinutes, 'minutes').toISOString(), + endDate: expect.any(String), + referenceNumber: expect.any(String), + licensee: { + ...p.licensee, + obfuscatedDob: expect.any(String) + } + })) + + mockCreateUpdateExpression(completionFields, expectedPermissions) + + docClient.send = jest.fn(command => { + if (command instanceof GetCommand) { + return Promise.resolve({ Item: mockRecord }) + } else if (command instanceof UpdateCommand) { + return Promise.resolve({ + Attributes: { ...mockRecord, ...completionFields, status: { id: TRANSACTION_STATUS.FINALISED } } + }) + } else { + return Promise.reject(new Error('Unknown command')) + } }) - AwsMock.DynamoDB.DocumentClient.__setResponse('get', { Item: mockRecord }) + sqs.sendMessage.mockResolvedValueOnce({ MessageId: 'Test_Message' }) await finaliseTransaction({ id: mockRecord.id, ...completionFields }) - expect(AwsMock.DynamoDB.DocumentClient.mockedMethods.update).toHaveBeenCalledWith( + const updateCommandInstance = docClient.send.mock.calls.find(call => call[0] instanceof UpdateCommand)[0] + const updatedPermissions = updateCommandInstance.input.ExpressionAttributeValues[':permissions'] + expect(updatedPermissions[0]).toEqual( expect.objectContaining({ - ExpressionAttributeValues: expect.objectContaining({ - ':permissions': expect.arrayContaining([ - expect.objectContaining({ - permitId: mockPermission.permitId, - startDate: moment(issueDate).add(startAfterPaymentMinutes, 'minutes').toISOString() - }) - ]) - }) + permitId: mockPermission.permitId, + startDate: moment(issueDate).add(startAfterPaymentMinutes, 'minutes').toISOString() }) ) } @@ -273,23 +351,42 @@ describe('transaction service', () => { mockPermission.startDate = startDate mockPermission.endDate = endDate const completionFields = getCompletionFields() - AwsMock.DynamoDB.DocumentClient.__setResponse('update', { - Attributes: { ...mockRecord, ...completionFields, status: { id: TRANSACTION_STATUS.FINALISED } } + + const expectedPermissions = mockRecord.permissions.map(p => ({ + ...p, + issueDate: p.issueDate ?? completionFields.payment.timestamp, + startDate, + endDate: expect.any(String), + referenceNumber: expect.any(String), + licensee: { + ...p.licensee, + obfuscatedDob: expect.any(String) + } + })) + + mockCreateUpdateExpression(completionFields, expectedPermissions) + + docClient.send = jest.fn(command => { + if (command instanceof GetCommand) { + return Promise.resolve({ Item: mockRecord }) + } else if (command instanceof UpdateCommand) { + return Promise.resolve({ + Attributes: { ...mockRecord, ...completionFields, status: { id: TRANSACTION_STATUS.FINALISED } } + }) + } else { + return Promise.reject(new Error('Unknown command')) + } }) - AwsMock.DynamoDB.DocumentClient.__setResponse('get', { Item: mockRecord }) + sqs.sendMessage.mockResolvedValueOnce({ MessageId: 'Test_Message' }) await finaliseTransaction({ id: mockRecord.id, ...completionFields }) - expect(AwsMock.DynamoDB.DocumentClient.mockedMethods.update).toHaveBeenCalledWith( + const updateCommandInstance = docClient.send.mock.calls[1][0] + const updatedPermissions = updateCommandInstance.input.ExpressionAttributeValues[':permissions'] + expect(updatedPermissions[0]).toEqual( expect.objectContaining({ - ExpressionAttributeValues: expect.objectContaining({ - ':permissions': expect.arrayContaining([ - expect.objectContaining({ - permitId: mockPermission.permitId, - startDate - }) - ]) - }) + permitId: mockPermission.permitId, + startDate }) ) }) @@ -308,23 +405,42 @@ describe('transaction service', () => { mockPermission.issueDate = issueDate mockPermission.startDate = startDate const completionFields = getCompletionFields() - AwsMock.DynamoDB.DocumentClient.__setResponse('update', { - Attributes: { ...mockRecord, ...completionFields, status: { id: TRANSACTION_STATUS.FINALISED } } + + const expectedPermissions = mockRecord.permissions.map(p => ({ + ...p, + issueDate: p.issueDate ?? completionFields.payment.timestamp, + startDate: p.startDate ?? moment(completionFields.payment.timestamp).add(START_AFTER_PAYMENT_MINUTES, 'minutes').toISOString(), + endDate, + referenceNumber: expect.any(String), + licensee: { + ...p.licensee, + obfuscatedDob: expect.any(String) + } + })) + + mockCreateUpdateExpression(completionFields, expectedPermissions) + + docClient.send = jest.fn(command => { + if (command instanceof GetCommand) { + return Promise.resolve({ Item: mockRecord }) + } else if (command instanceof UpdateCommand) { + return Promise.resolve({ + Attributes: { ...mockRecord, ...completionFields, status: { id: TRANSACTION_STATUS.FINALISED } } + }) + } else { + return Promise.reject(new Error('Unknown command')) + } }) - AwsMock.DynamoDB.DocumentClient.__setResponse('get', { Item: mockRecord }) + sqs.sendMessage.mockResolvedValueOnce({ MessageId: 'Test_Message' }) await finaliseTransaction({ id: mockRecord.id, ...completionFields }) - expect(AwsMock.DynamoDB.DocumentClient.mockedMethods.update).toHaveBeenCalledWith( + const updateCommandInstance = docClient.send.mock.calls[1][0] + const updatedPermissions = updateCommandInstance.input.ExpressionAttributeValues[':permissions'] + expect(updatedPermissions[0]).toEqual( expect.objectContaining({ - ExpressionAttributeValues: expect.objectContaining({ - ':permissions': expect.arrayContaining([ - expect.objectContaining({ - permitId: mockPermission.permitId, - endDate - }) - ]) - }) + permitId: mockPermission.permitId, + endDate }) ) }) @@ -341,23 +457,42 @@ describe('transaction service', () => { mockPermission.startDate = startDate mockPermission.endDate = endDate const completionFields = getCompletionFields() - AwsMock.DynamoDB.DocumentClient.__setResponse('update', { - Attributes: { ...mockRecord, ...completionFields, status: { id: TRANSACTION_STATUS.FINALISED } } + + const expectedPermissions = mockRecord.permissions.map(p => ({ + ...p, + issueDate: p.issueDate ?? completionFields.payment.timestamp, + startDate, + endDate, + referenceNumber: expect.any(String), + licensee: { + ...p.licensee, + obfuscatedDob: expect.any(String) + } + })) + + mockCreateUpdateExpression(completionFields, expectedPermissions) + + docClient.send = jest.fn(command => { + if (command instanceof GetCommand) { + return Promise.resolve({ Item: mockRecord }) + } else if (command instanceof UpdateCommand) { + return Promise.resolve({ + Attributes: { ...mockRecord, ...completionFields, status: { id: TRANSACTION_STATUS.FINALISED } } + }) + } else { + return Promise.reject(new Error('Unknown command')) + } }) - AwsMock.DynamoDB.DocumentClient.__setResponse('get', { Item: mockRecord }) + sqs.sendMessage.mockResolvedValueOnce({ MessageId: 'Test_Message' }) await finaliseTransaction({ id: mockRecord.id, ...completionFields }) - expect(AwsMock.DynamoDB.DocumentClient.mockedMethods.update).toHaveBeenCalledWith( + const updateCommandInstance = docClient.send.mock.calls[1][0] + const updatedPermissions = updateCommandInstance.input.ExpressionAttributeValues[':permissions'] + expect(updatedPermissions[0]).toEqual( expect.objectContaining({ - ExpressionAttributeValues: expect.objectContaining({ - ':permissions': expect.arrayContaining([ - expect.objectContaining({ - permitId: mockPermission.permitId, - endDate - }) - ]) - }) + permitId: mockPermission.permitId, + endDate }) ) }) @@ -378,24 +513,43 @@ describe('transaction service', () => { mockPermission.startDate = startDate mockPermission.endDate = endDate const completionFields = getCompletionFields() - AwsMock.DynamoDB.DocumentClient.__setResponse('update', { - Attributes: { ...mockRecord, ...completionFields, status: { id: TRANSACTION_STATUS.FINALISED } } + + const expectedPermissions = mockRecord.permissions.map(p => ({ + ...p, + issueDate: p.issueDate ?? completionFields.payment.timestamp, + startDate, + endDate, + referenceNumber: expect.any(String), + licensee: { + ...p.licensee, + obfuscatedDob: expect.any(String) + } + })) + + mockCreateUpdateExpression(completionFields, expectedPermissions) + + docClient.send = jest.fn(command => { + if (command instanceof GetCommand) { + return Promise.resolve({ Item: mockRecord }) + } else if (command instanceof UpdateCommand) { + return Promise.resolve({ + Attributes: { ...mockRecord, ...completionFields, status: { id: TRANSACTION_STATUS.FINALISED } } + }) + } else { + return Promise.reject(new Error('Unknown command')) + } }) - AwsMock.DynamoDB.DocumentClient.__setResponse('get', { Item: mockRecord }) + sqs.sendMessage.mockResolvedValueOnce({ MessageId: 'Test_Message' }) await finaliseTransaction({ id: mockRecord.id, ...completionFields }) - expect(AwsMock.DynamoDB.DocumentClient.mockedMethods.update).toHaveBeenCalledWith( + const updateCommandInstance = docClient.send.mock.calls[1][0] + const updatedPermissions = updateCommandInstance.input.ExpressionAttributeValues[':permissions'] + expect(updatedPermissions[0]).toEqual( expect.objectContaining({ - ExpressionAttributeValues: expect.objectContaining({ - ':permissions': expect.arrayContaining([ - expect.objectContaining({ - permitId: mockPermission.permitId, - startDate, - endDate - }) - ]) - }) + permitId: mockPermission.permitId, + startDate, + endDate }) ) } @@ -405,29 +559,35 @@ describe('transaction service', () => { ['2021-09-30T17:14:01.892Z', '2021-09-30T17:14:01.892Z'], ['2021-09-30T23:14:01.892Z', '2021-09-30T23:00:49.892Z'], ['2021-09-30T22:14:01.892Z', '2021-09-30T21:44:01.892Z'] - ])('passes a permission with a start date when generating a permission number', async (issueDate, startDate) => { + ])('passes a permission with a start date when generating a permission number', async (issueDate, expectedStartDate) => { const mockRecord = mockStagedTransactionRecord() const [mockPermission] = mockRecord.permissions const completionFields = getCompletionFields(issueDate) mockPermission.issueDate = issueDate delete mockPermission.startDate - AwsMock.DynamoDB.DocumentClient.__setResponse('get', { Item: mockRecord }) - AwsMock.DynamoDB.DocumentClient.__setResponse('update', { - Attributes: { ...mockRecord, ...completionFields, status: { id: TRANSACTION_STATUS.FINALISED } } + + docClient.send = jest.fn(command => { + if (command instanceof GetCommand) { + return Promise.resolve({ Item: mockRecord }) + } else if (command instanceof UpdateCommand) { + return Promise.resolve({ + Attributes: { ...mockRecord, ...completionFields, status: { id: TRANSACTION_STATUS.FINALISED } } + }) + } else { + return Promise.reject(new Error('Unknown command')) + } }) - AwsMock.SQS.__setResponse('sendMessage', { MessageId: 'Test_Message' }) - // have to do this as Jest holds calling arguments by reference, so we don't - // get the permission as it was when generatePermissionNumber was called but how it - // ends up by the end of finaliseTransaction... - let permission + sqs.sendMessage.mockResolvedValueOnce({ MessageId: 'Test_Message' }) + + let capturedPermission permissionsService.generatePermissionNumber.mockImplementationOnce(p => { - permission = JSON.parse(JSON.stringify(p)) - return startDate + capturedPermission = { ...p } + return 'some-permission-number' }) await finaliseTransaction({ id: mockRecord.id, ...completionFields }) - expect(permission).toEqual( + expect(capturedPermission).toEqual( expect.objectContaining({ permitId: mockPermission.permitId, startDate: moment(completionFields.payment.timestamp).add(START_AFTER_PAYMENT_MINUTES, 'minutes').toISOString() diff --git a/packages/sales-api-service/src/services/transactions/finalise-transaction.js b/packages/sales-api-service/src/services/transactions/finalise-transaction.js index 7f6a0c3be..dc863f53b 100644 --- a/packages/sales-api-service/src/services/transactions/finalise-transaction.js +++ b/packages/sales-api-service/src/services/transactions/finalise-transaction.js @@ -6,9 +6,11 @@ import { TRANSACTION_STAGING_TABLE, TRANSACTION_QUEUE } from '../../config.js' import { POCL_TRANSACTION_SOURCES, START_AFTER_PAYMENT_MINUTES } from '@defra-fish/business-rules-lib' import moment from 'moment' import Boom from '@hapi/boom' -import { AWS } from '@defra-fish/connectors-lib' import db from 'debug' -const { sqs, docClient } = AWS() +import { sqs } from '@defra-fish/connectors-lib' +import { docClient } from '../../../../connectors-lib/src/aws.js' +import { UpdateCommand } from '@aws-sdk/lib-dynamodb' + const debug = db('sales:transactions') const getAdjustedStartDate = ({ issueDate, startDate, dataSource }) => { @@ -48,8 +50,8 @@ export async function finaliseTransaction ({ id, ...payload }) { permission.licensee.obfuscatedDob = await getObfuscatedDob(permission.licensee) } - const { Attributes: updatedRecord } = await docClient - .update({ + const { Attributes: updatedRecord } = await docClient.send( + new UpdateCommand({ TableName: TRANSACTION_STAGING_TABLE.TableName, Key: { id }, ...docClient.createUpdateExpression({ @@ -59,17 +61,15 @@ export async function finaliseTransaction ({ id, ...payload }) { }), ReturnValues: 'ALL_NEW' }) - .promise() + ) debug('Updated transaction record for identifier %s', id) - const receipt = await sqs - .sendMessage({ - QueueUrl: TRANSACTION_QUEUE.Url, - MessageGroupId: id, - MessageDeduplicationId: id, - MessageBody: JSON.stringify({ id }) - }) - .promise() + const receipt = await sqs.sendMessage({ + QueueUrl: TRANSACTION_QUEUE.Url, + MessageGroupId: id, + MessageDeduplicationId: id, + MessageBody: JSON.stringify({ id }) + }) debug('Sent transaction %s to staging queue with message-id %s', id, receipt.MessageId) updatedRecord.status.messageId = receipt.MessageId