From ebf87767d07c8c1f6f369159c8e4d401832b6f94 Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Fri, 27 Mar 2026 15:58:18 +0000 Subject: [PATCH] CCM-15876: Replay event script --- package-lock.json | 1320 +++++++++++++++++++++- package.json | 3 +- scripts/replay-events/download-events.ts | 123 ++ scripts/replay-events/package.json | 14 + scripts/replay-events/replay-events.ts | 61 + 5 files changed, 1514 insertions(+), 7 deletions(-) create mode 100644 scripts/replay-events/download-events.ts create mode 100644 scripts/replay-events/package.json create mode 100644 scripts/replay-events/replay-events.ts diff --git a/package-lock.json b/package-lock.json index 78fb2ec3..19957f26 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,8 @@ "pact-contracts", "scripts/utilities/*", "tests", - "tests/contracts/*" + "tests/contracts/*", + "scripts/replay-events" ], "devDependencies": { "@aws-sdk/client-api-gateway": "^3.906.0", @@ -110,7 +111,7 @@ }, "internal/events": { "name": "@nhsdigital/nhs-notify-event-schemas-supplier-api", - "version": "1.0.16", + "version": "1.0.17", "license": "MIT", "dependencies": { "@asyncapi/bundler": "^0.6.4", @@ -171,6 +172,7 @@ "@aws-sdk/client-sns": "^3.943.0", "@aws-sdk/util-dynamodb": "^3.943.0", "@internal/datastore": "^0.1.0", + "@internal/event-builders": "*", "@internal/helpers": "^0.1.0", "@nhsdigital/nhs-notify-event-schemas-supplier-api": "*", "aws-embedded-metrics": "^4.2.1", @@ -15159,7 +15161,6 @@ "version": "4.13.6", "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz", "integrity": "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==", - "dev": true, "license": "MIT", "dependencies": { "resolve-pkg-maps": "^1.0.0" @@ -18728,6 +18729,10 @@ "resolved": "lambdas/mi-updates-transformer", "link": true }, + "node_modules/nhs-notify-supplier-api-repla-events": { + "resolved": "scripts/replay-events", + "link": true + }, "node_modules/nhs-notify-supplier-api-suppliers-data-utility": { "resolved": "scripts/utilities/supplier-data", "link": true @@ -20816,7 +20821,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" @@ -22878,7 +22882,6 @@ "version": "4.21.0", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", - "dev": true, "license": "MIT", "dependencies": { "esbuild": "~0.27.0", @@ -23057,7 +23060,6 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -24170,6 +24172,1312 @@ "version": "1.0.1", "license": "MIT" }, + "scripts/replay-events": { + "name": "nhs-notify-supplier-api-repla-events", + "dependencies": { + "@aws-sdk/client-s3": "^3.1008.0", + "@aws-sdk/client-sns": "^3.1008.0", + "tsx": "^4.20.6", + "typescript": "^5.9.3" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/client-s3": { + "version": "3.1018.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.1018.0.tgz", + "integrity": "sha512-BiGKMjrkAJkyse1ECpVyxVYugf82FB3cM9zgKpx3boFuWobyolG5ri6XjoMIY8fpHddaO8ZClXEedACyelSLWA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha1-browser": "5.2.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.973.25", + "@aws-sdk/credential-provider-node": "^3.972.26", + "@aws-sdk/middleware-bucket-endpoint": "^3.972.8", + "@aws-sdk/middleware-expect-continue": "^3.972.8", + "@aws-sdk/middleware-flexible-checksums": "^3.974.5", + "@aws-sdk/middleware-host-header": "^3.972.8", + "@aws-sdk/middleware-location-constraint": "^3.972.8", + "@aws-sdk/middleware-logger": "^3.972.8", + "@aws-sdk/middleware-recursion-detection": "^3.972.9", + "@aws-sdk/middleware-sdk-s3": "^3.972.26", + "@aws-sdk/middleware-ssec": "^3.972.8", + "@aws-sdk/middleware-user-agent": "^3.972.26", + "@aws-sdk/region-config-resolver": "^3.972.10", + "@aws-sdk/signature-v4-multi-region": "^3.996.14", + "@aws-sdk/types": "^3.973.6", + "@aws-sdk/util-endpoints": "^3.996.5", + "@aws-sdk/util-user-agent-browser": "^3.972.8", + "@aws-sdk/util-user-agent-node": "^3.973.12", + "@smithy/config-resolver": "^4.4.13", + "@smithy/core": "^3.23.12", + "@smithy/eventstream-serde-browser": "^4.2.12", + "@smithy/eventstream-serde-config-resolver": "^4.3.12", + "@smithy/eventstream-serde-node": "^4.2.12", + "@smithy/fetch-http-handler": "^5.3.15", + "@smithy/hash-blob-browser": "^4.2.13", + "@smithy/hash-node": "^4.2.12", + "@smithy/hash-stream-node": "^4.2.12", + "@smithy/invalid-dependency": "^4.2.12", + "@smithy/md5-js": "^4.2.12", + "@smithy/middleware-content-length": "^4.2.12", + "@smithy/middleware-endpoint": "^4.4.27", + "@smithy/middleware-retry": "^4.4.44", + "@smithy/middleware-serde": "^4.2.15", + "@smithy/middleware-stack": "^4.2.12", + "@smithy/node-config-provider": "^4.3.12", + "@smithy/node-http-handler": "^4.5.0", + "@smithy/protocol-http": "^5.3.12", + "@smithy/smithy-client": "^4.12.7", + "@smithy/types": "^4.13.1", + "@smithy/url-parser": "^4.2.12", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-body-length-browser": "^4.2.2", + "@smithy/util-body-length-node": "^4.2.3", + "@smithy/util-defaults-mode-browser": "^4.3.43", + "@smithy/util-defaults-mode-node": "^4.2.47", + "@smithy/util-endpoints": "^3.3.3", + "@smithy/util-middleware": "^4.2.12", + "@smithy/util-retry": "^4.2.12", + "@smithy/util-stream": "^4.5.20", + "@smithy/util-utf8": "^4.2.2", + "@smithy/util-waiter": "^4.2.13", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/client-sns": { + "version": "3.1018.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sns/-/client-sns-3.1018.0.tgz", + "integrity": "sha512-WDNoG6nD4k9RahAoSp3oBy+8GPgs4ZseUkb2bIZLHW0TtsgsCiw7dKKUqi1FTLu7CqbJ18ahwG5dzj/A9skGlQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.973.25", + "@aws-sdk/credential-provider-node": "^3.972.26", + "@aws-sdk/middleware-host-header": "^3.972.8", + "@aws-sdk/middleware-logger": "^3.972.8", + "@aws-sdk/middleware-recursion-detection": "^3.972.9", + "@aws-sdk/middleware-user-agent": "^3.972.26", + "@aws-sdk/region-config-resolver": "^3.972.10", + "@aws-sdk/types": "^3.973.6", + "@aws-sdk/util-endpoints": "^3.996.5", + "@aws-sdk/util-user-agent-browser": "^3.972.8", + "@aws-sdk/util-user-agent-node": "^3.973.12", + "@smithy/config-resolver": "^4.4.13", + "@smithy/core": "^3.23.12", + "@smithy/fetch-http-handler": "^5.3.15", + "@smithy/hash-node": "^4.2.12", + "@smithy/invalid-dependency": "^4.2.12", + "@smithy/middleware-content-length": "^4.2.12", + "@smithy/middleware-endpoint": "^4.4.27", + "@smithy/middleware-retry": "^4.4.44", + "@smithy/middleware-serde": "^4.2.15", + "@smithy/middleware-stack": "^4.2.12", + "@smithy/node-config-provider": "^4.3.12", + "@smithy/node-http-handler": "^4.5.0", + "@smithy/protocol-http": "^5.3.12", + "@smithy/smithy-client": "^4.12.7", + "@smithy/types": "^4.13.1", + "@smithy/url-parser": "^4.2.12", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-body-length-browser": "^4.2.2", + "@smithy/util-body-length-node": "^4.2.3", + "@smithy/util-defaults-mode-browser": "^4.3.43", + "@smithy/util-defaults-mode-node": "^4.2.47", + "@smithy/util-endpoints": "^3.3.3", + "@smithy/util-middleware": "^4.2.12", + "@smithy/util-retry": "^4.2.12", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/core": { + "version": "3.973.25", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.25.tgz", + "integrity": "sha512-TNrx7eq6nKNOO62HWPqoBqPLXEkW6nLZQGwjL6lq1jZtigWYbK1NbCnT7mKDzbLMHZfuOECUt3n6CzxjUW9HWQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.6", + "@aws-sdk/xml-builder": "^3.972.16", + "@smithy/core": "^3.23.12", + "@smithy/node-config-provider": "^4.3.12", + "@smithy/property-provider": "^4.2.12", + "@smithy/protocol-http": "^5.3.12", + "@smithy/signature-v4": "^5.3.12", + "@smithy/smithy-client": "^4.12.7", + "@smithy/types": "^4.13.1", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-middleware": "^4.2.12", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/crc64-nvme": { + "version": "3.972.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/crc64-nvme/-/crc64-nvme-3.972.5.tgz", + "integrity": "sha512-2VbTstbjKdT+yKi8m7b3a9CiVac+pL/IY2PHJwsaGkkHmuuqkJZIErPck1h6P3T9ghQMLSdMPyW6Qp7Di5swFg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/credential-provider-env": { + "version": "3.972.23", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.23.tgz", + "integrity": "sha512-EamaclJcCEaPHp6wiVknNMM2RlsPMjAHSsYSFLNENBM8Wz92QPc6cOn3dif6vPDQt0Oo4IEghDy3NMDCzY/IvA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.25", + "@aws-sdk/types": "^3.973.6", + "@smithy/property-provider": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/credential-provider-http": { + "version": "3.972.25", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.25.tgz", + "integrity": "sha512-qPymamdPcLp6ugoVocG1y5r69ScNiRzb0hogX25/ij+Wz7c7WnsgjLTaz7+eB5BfRxeyUwuw5hgULMuwOGOpcw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.25", + "@aws-sdk/types": "^3.973.6", + "@smithy/fetch-http-handler": "^5.3.15", + "@smithy/node-http-handler": "^4.5.0", + "@smithy/property-provider": "^4.2.12", + "@smithy/protocol-http": "^5.3.12", + "@smithy/smithy-client": "^4.12.7", + "@smithy/types": "^4.13.1", + "@smithy/util-stream": "^4.5.20", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.972.25", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.25.tgz", + "integrity": "sha512-G/v/PicYn4qs7xCv4vT6I4QKdvMyRvsgIFNBkUueCGlbLo7/PuKcNKgUozmLSsaYnE7jIl6UrfkP07EUubr48w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.25", + "@aws-sdk/credential-provider-env": "^3.972.23", + "@aws-sdk/credential-provider-http": "^3.972.25", + "@aws-sdk/credential-provider-login": "^3.972.25", + "@aws-sdk/credential-provider-process": "^3.972.23", + "@aws-sdk/credential-provider-sso": "^3.972.25", + "@aws-sdk/credential-provider-web-identity": "^3.972.25", + "@aws-sdk/nested-clients": "^3.996.15", + "@aws-sdk/types": "^3.973.6", + "@smithy/credential-provider-imds": "^4.2.12", + "@smithy/property-provider": "^4.2.12", + "@smithy/shared-ini-file-loader": "^4.4.7", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/credential-provider-login": { + "version": "3.972.25", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.25.tgz", + "integrity": "sha512-bUdmyJeVua7SmD+g2a65x2/0YqsGn4K2k4GawI43js0odaNaIzpIhLtHehUnPnfLuyhPWbJR1NyuIO4iMVfM0w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.25", + "@aws-sdk/nested-clients": "^3.996.15", + "@aws-sdk/types": "^3.973.6", + "@smithy/property-provider": "^4.2.12", + "@smithy/protocol-http": "^5.3.12", + "@smithy/shared-ini-file-loader": "^4.4.7", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.972.26", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.26.tgz", + "integrity": "sha512-5XSK74rCXxCNj+UWv5bjq1EccYkiyW4XOHFU9NXnsCcQF8dJuHdua1qFg0m/LIwVOWklbKsrcnMtfxIXwgvwzQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "^3.972.23", + "@aws-sdk/credential-provider-http": "^3.972.25", + "@aws-sdk/credential-provider-ini": "^3.972.25", + "@aws-sdk/credential-provider-process": "^3.972.23", + "@aws-sdk/credential-provider-sso": "^3.972.25", + "@aws-sdk/credential-provider-web-identity": "^3.972.25", + "@aws-sdk/types": "^3.973.6", + "@smithy/credential-provider-imds": "^4.2.12", + "@smithy/property-provider": "^4.2.12", + "@smithy/shared-ini-file-loader": "^4.4.7", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/credential-provider-process": { + "version": "3.972.23", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.23.tgz", + "integrity": "sha512-IL/TFW59++b7MpHserjUblGrdP5UXy5Ekqqx1XQkERXBFJcZr74I7VaSrQT5dxdRMU16xGK4L0RQ5fQG1pMgnA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.25", + "@aws-sdk/types": "^3.973.6", + "@smithy/property-provider": "^4.2.12", + "@smithy/shared-ini-file-loader": "^4.4.7", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.972.25", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.25.tgz", + "integrity": "sha512-r4OGAfHmlEa1QBInHWz+/dOD4tRljcjVNQe9wJ/AJNXEj1d2WdsRLppvRFImRV6FIs+bTpjtL0a23V5ELQpRPw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.25", + "@aws-sdk/nested-clients": "^3.996.15", + "@aws-sdk/token-providers": "3.1018.0", + "@aws-sdk/types": "^3.973.6", + "@smithy/property-provider": "^4.2.12", + "@smithy/shared-ini-file-loader": "^4.4.7", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.972.25", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.25.tgz", + "integrity": "sha512-uM1OtoJgj+yK3MlAmda8uR9WJJCdm5HB25JyCeFL5a5q1Fbafalf4uKidFO3/L0Pgd+Fsflkb4cM6jHIswi3QQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.25", + "@aws-sdk/nested-clients": "^3.996.15", + "@aws-sdk/types": "^3.973.6", + "@smithy/property-provider": "^4.2.12", + "@smithy/shared-ini-file-loader": "^4.4.7", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/middleware-bucket-endpoint": { + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.972.8.tgz", + "integrity": "sha512-WR525Rr2QJSETa9a050isktyWi/4yIGcmY3BQ1kpHqb0LqUglQHCS8R27dTJxxWNZvQ0RVGtEZjTCbZJpyF3Aw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.6", + "@aws-sdk/util-arn-parser": "^3.972.3", + "@smithy/node-config-provider": "^4.3.12", + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "@smithy/util-config-provider": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/middleware-expect-continue": { + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.972.8.tgz", + "integrity": "sha512-5DTBTiotEES1e2jOHAq//zyzCjeMB78lEHd35u15qnrid4Nxm7diqIf9fQQ3Ov0ChH1V3Vvt13thOnrACmfGVQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.6", + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.974.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.974.5.tgz", + "integrity": "sha512-SPSvF0G1t8m8CcB0L+ClNFszzQOvXaxmRj25oRWDf6aU+TuN2PXPFAJ9A6lt1IvX4oGAqqbTdMPTYs/SSHUYYQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-crypto/util": "5.2.0", + "@aws-sdk/core": "^3.973.25", + "@aws-sdk/crc64-nvme": "^3.972.5", + "@aws-sdk/types": "^3.973.6", + "@smithy/is-array-buffer": "^4.2.2", + "@smithy/node-config-provider": "^4.3.12", + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "@smithy/util-middleware": "^4.2.12", + "@smithy/util-stream": "^4.5.20", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/middleware-host-header": { + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.972.8.tgz", + "integrity": "sha512-wAr2REfKsqoKQ+OkNqvOShnBoh+nkPurDKW7uAeVSu6kUECnWlSJiPvnoqxGlfousEY/v9LfS9sNc46hjSYDIQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.6", + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/middleware-location-constraint": { + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.972.8.tgz", + "integrity": "sha512-KaUoFuoFPziIa98DSQsTPeke1gvGXlc5ZGMhy+b+nLxZ4A7jmJgLzjEF95l8aOQN2T/qlPP3MrAyELm8ExXucw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.6", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/middleware-logger": { + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.972.8.tgz", + "integrity": "sha512-CWl5UCM57WUFaFi5kB7IBY1UmOeLvNZAZ2/OZ5l20ldiJ3TiIz1pC65gYj8X0BCPWkeR1E32mpsCk1L1I4n+lA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.6", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.972.9", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.972.9.tgz", + "integrity": "sha512-/Wt5+CT8dpTFQxEJ9iGy/UGrXr7p2wlIOEHvIr/YcHYByzoLjrqkYqXdJjd9UIgWjv7eqV2HnFJen93UTuwfTQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.6", + "@aws/lambda-invoke-store": "^0.2.2", + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.972.26", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.26.tgz", + "integrity": "sha512-5q7UGSTtt7/KF0Os8wj2VZtlLxeWJVb0e2eDrDJlWot2EIxUNKDDMPFq/FowUqrwZ40rO2bu6BypxaKNvQhI+g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.25", + "@aws-sdk/types": "^3.973.6", + "@aws-sdk/util-arn-parser": "^3.972.3", + "@smithy/core": "^3.23.12", + "@smithy/node-config-provider": "^4.3.12", + "@smithy/protocol-http": "^5.3.12", + "@smithy/signature-v4": "^5.3.12", + "@smithy/smithy-client": "^4.12.7", + "@smithy/types": "^4.13.1", + "@smithy/util-config-provider": "^4.2.2", + "@smithy/util-middleware": "^4.2.12", + "@smithy/util-stream": "^4.5.20", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/middleware-ssec": { + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.972.8.tgz", + "integrity": "sha512-wqlK0yO/TxEC2UsY9wIlqeeutF6jjLe0f96Pbm40XscTo57nImUk9lBcw0dPgsm0sppFtAkSlDrfpK+pC30Wqw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.6", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.972.26", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.26.tgz", + "integrity": "sha512-AilFIh4rI/2hKyyGN6XrB0yN96W2o7e7wyrPWCM6QjZM1mcC/pVkW3IWWRvuBWMpVP8Fg+rMpbzeLQ6dTM4gig==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.25", + "@aws-sdk/types": "^3.973.6", + "@aws-sdk/util-endpoints": "^3.996.5", + "@smithy/core": "^3.23.12", + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "@smithy/util-retry": "^4.2.12", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/nested-clients": { + "version": "3.996.15", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.996.15.tgz", + "integrity": "sha512-k6WAVNkub5DrU46iPQvH1m0xc1n+0dX79+i287tYJzf5g1yU2rX3uf4xNeL5JvK1NtYgfwMnsxHqhOXFBn367A==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.973.25", + "@aws-sdk/middleware-host-header": "^3.972.8", + "@aws-sdk/middleware-logger": "^3.972.8", + "@aws-sdk/middleware-recursion-detection": "^3.972.9", + "@aws-sdk/middleware-user-agent": "^3.972.26", + "@aws-sdk/region-config-resolver": "^3.972.10", + "@aws-sdk/types": "^3.973.6", + "@aws-sdk/util-endpoints": "^3.996.5", + "@aws-sdk/util-user-agent-browser": "^3.972.8", + "@aws-sdk/util-user-agent-node": "^3.973.12", + "@smithy/config-resolver": "^4.4.13", + "@smithy/core": "^3.23.12", + "@smithy/fetch-http-handler": "^5.3.15", + "@smithy/hash-node": "^4.2.12", + "@smithy/invalid-dependency": "^4.2.12", + "@smithy/middleware-content-length": "^4.2.12", + "@smithy/middleware-endpoint": "^4.4.27", + "@smithy/middleware-retry": "^4.4.44", + "@smithy/middleware-serde": "^4.2.15", + "@smithy/middleware-stack": "^4.2.12", + "@smithy/node-config-provider": "^4.3.12", + "@smithy/node-http-handler": "^4.5.0", + "@smithy/protocol-http": "^5.3.12", + "@smithy/smithy-client": "^4.12.7", + "@smithy/types": "^4.13.1", + "@smithy/url-parser": "^4.2.12", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-body-length-browser": "^4.2.2", + "@smithy/util-body-length-node": "^4.2.3", + "@smithy/util-defaults-mode-browser": "^4.3.43", + "@smithy/util-defaults-mode-node": "^4.2.47", + "@smithy/util-endpoints": "^3.3.3", + "@smithy/util-middleware": "^4.2.12", + "@smithy/util-retry": "^4.2.12", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/region-config-resolver": { + "version": "3.972.10", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.972.10.tgz", + "integrity": "sha512-1dq9ToC6e070QvnVhhbAs3bb5r6cQ10gTVc6cyRV5uvQe7P138TV2uG2i6+Yok4bAkVAcx5AqkTEBUvWEtBlsQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.6", + "@smithy/config-resolver": "^4.4.13", + "@smithy/node-config-provider": "^4.3.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.996.14", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.14.tgz", + "integrity": "sha512-4nZSrBr1NO+48HCM/6BRU8mnRjuHZjcpziCvLXZk5QVftwWz5Mxqbhwdz4xf7WW88buaTB8uRO2MHklSX1m0vg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-sdk-s3": "^3.972.26", + "@aws-sdk/types": "^3.973.6", + "@smithy/protocol-http": "^5.3.12", + "@smithy/signature-v4": "^5.3.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/token-providers": { + "version": "3.1018.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1018.0.tgz", + "integrity": "sha512-97OPNJHy37wmGOX44xAcu6E9oSTiqK9uPcy/fWpmN5uB3JuEp1f6x60Xot/jp+FxwhQWIFUsVJFnm3QKqt7T6Q==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.25", + "@aws-sdk/nested-clients": "^3.996.15", + "@aws-sdk/types": "^3.973.6", + "@smithy/property-provider": "^4.2.12", + "@smithy/shared-ini-file-loader": "^4.4.7", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/types": { + "version": "3.973.6", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.973.6.tgz", + "integrity": "sha512-Atfcy4E++beKtwJHiDln2Nby8W/mam64opFPTiHEqgsthqeydFS1pY+OUlN1ouNOmf8ArPU/6cDS65anOP3KQw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/util-arn-parser": { + "version": "3.972.3", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.972.3.tgz", + "integrity": "sha512-HzSD8PMFrvgi2Kserxuff5VitNq2sgf3w9qxmskKDiDTThWfVteJxuCS9JXiPIPtmCrp+7N9asfIaVhBFORllA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/util-endpoints": { + "version": "3.996.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.996.5.tgz", + "integrity": "sha512-Uh93L5sXFNbyR5sEPMzUU8tJ++Ku97EY4udmC01nB8Zu+xfBPwpIwJ6F7snqQeq8h2pf+8SGN5/NoytfKgYPIw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.6", + "@smithy/types": "^4.13.1", + "@smithy/url-parser": "^4.2.12", + "@smithy/util-endpoints": "^3.3.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.972.8.tgz", + "integrity": "sha512-B3KGXJviV2u6Cdw2SDY2aDhoJkVfY/Q/Trwk2CMSkikE1Oi6gRzxhvhIfiRpHfmIsAhV4EA54TVEX8K6CbHbkA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.6", + "@smithy/types": "^4.13.1", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "scripts/replay-events/node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.973.12", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.12.tgz", + "integrity": "sha512-8phW0TS8ntENJgDcFewYT/Q8dOmarpvSxEjATu2GUBAutiHr++oEGCiBUwxslCMNvwW2cAPZNT53S/ym8zm/gg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-user-agent": "^3.972.26", + "@aws-sdk/types": "^3.973.6", + "@smithy/node-config-provider": "^4.3.12", + "@smithy/types": "^4.13.1", + "@smithy/util-config-provider": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "scripts/replay-events/node_modules/@aws-sdk/xml-builder": { + "version": "3.972.16", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.16.tgz", + "integrity": "sha512-iu2pyvaqmeatIJLURLqx9D+4jKAdTH20ntzB6BFwjyN7V960r4jK32mx0Zf7YbtOYAbmbtQfDNuL60ONinyw7A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "fast-xml-parser": "5.5.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/abort-controller": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.12.tgz", + "integrity": "sha512-xolrFw6b+2iYGl6EcOL7IJY71vvyZ0DJ3mcKtpykqPe2uscwtzDZJa1uVQXyP7w9Dd+kGwYnPbMsJrGISKiY/Q==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/config-resolver": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.13.tgz", + "integrity": "sha512-iIzMC5NmOUP6WL6o8iPBjFhUhBZ9pPjpUpQYWMUFQqKyXXzOftbfK8zcQCz/jFV1Psmf05BK5ypx4K2r4Tnwdg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.12", + "@smithy/types": "^4.13.1", + "@smithy/util-config-provider": "^4.2.2", + "@smithy/util-endpoints": "^3.3.3", + "@smithy/util-middleware": "^4.2.12", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/core": { + "version": "3.23.12", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.23.12.tgz", + "integrity": "sha512-o9VycsYNtgC+Dy3I0yrwCqv9CWicDnke0L7EVOrZtJpjb2t0EjaEofmMrYc0T1Kn3yk32zm6cspxF9u9Bj7e5w==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "@smithy/url-parser": "^4.2.12", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-body-length-browser": "^4.2.2", + "@smithy/util-middleware": "^4.2.12", + "@smithy/util-stream": "^4.5.20", + "@smithy/util-utf8": "^4.2.2", + "@smithy/uuid": "^1.1.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/credential-provider-imds": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.12.tgz", + "integrity": "sha512-cr2lR792vNZcYMriSIj+Um3x9KWrjcu98kn234xA6reOAFMmbRpQMOv8KPgEmLLtx3eldU6c5wALKFqNOhugmg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.12", + "@smithy/property-provider": "^4.2.12", + "@smithy/types": "^4.13.1", + "@smithy/url-parser": "^4.2.12", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/eventstream-codec": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.2.12.tgz", + "integrity": "sha512-FE3bZdEl62ojmy8x4FHqxq2+BuOHlcxiH5vaZ6aqHJr3AIZzwF5jfx8dEiU/X0a8RboyNDjmXjlbr8AdEyLgiA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.13.1", + "@smithy/util-hex-encoding": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/eventstream-serde-browser": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.12.tgz", + "integrity": "sha512-XUSuMxlTxV5pp4VpqZf6Sa3vT/Q75FVkLSpSSE3KkWBvAQWeuWt1msTv8fJfgA4/jcJhrbrbMzN1AC/hvPmm5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/eventstream-serde-universal": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "4.3.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.12.tgz", + "integrity": "sha512-7epsAZ3QvfHkngz6RXQYseyZYHlmWXSTPOfPmXkiS+zA6TBNo1awUaMFL9vxyXlGdoELmCZyZe1nQE+imbmV+Q==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/eventstream-serde-node": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.12.tgz", + "integrity": "sha512-D1pFuExo31854eAvg89KMn9Oab/wEeJR6Buy32B49A9Ogdtx5fwZPqBHUlDzaCDpycTFk2+fSQgX689Qsk7UGA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/eventstream-serde-universal": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/eventstream-serde-universal": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.12.tgz", + "integrity": "sha512-+yNuTiyBACxOJUTvbsNsSOfH9G9oKbaJE1lNL3YHpGcuucl6rPZMi3nrpehpVOVR2E07YqFFmtwpImtpzlouHQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/eventstream-codec": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/fetch-http-handler": { + "version": "5.3.15", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.15.tgz", + "integrity": "sha512-T4jFU5N/yiIfrtrsb9uOQn7RdELdM/7HbyLNr6uO/mpkj1ctiVs7CihVr51w4LyQlXWDpXFn4BElf1WmQvZu/A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.12", + "@smithy/querystring-builder": "^4.2.12", + "@smithy/types": "^4.13.1", + "@smithy/util-base64": "^4.3.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/hash-blob-browser": { + "version": "4.2.13", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.2.13.tgz", + "integrity": "sha512-YrF4zWKh+ghLuquldj6e/RzE3xZYL8wIPfkt0MqCRphVICjyyjH8OwKD7LLlKpVEbk4FLizFfC1+gwK6XQdR3g==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/chunked-blob-reader": "^5.2.2", + "@smithy/chunked-blob-reader-native": "^4.2.3", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/hash-node": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.12.tgz", + "integrity": "sha512-QhBYbGrbxTkZ43QoTPrK72DoYviDeg6YKDrHTMJbbC+A0sml3kSjzFtXP7BtbyJnXojLfTQldGdUR0RGD8dA3w==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "@smithy/util-buffer-from": "^4.2.2", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/hash-stream-node": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.2.12.tgz", + "integrity": "sha512-O3YbmGExeafuM/kP7Y8r6+1y0hIh3/zn6GROx0uNlB54K9oihAL75Qtc+jFfLNliTi6pxOAYZrRKD9A7iA6UFw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/invalid-dependency": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.12.tgz", + "integrity": "sha512-/4F1zb7Z8LOu1PalTdESFHR0RbPwHd3FcaG1sI3UEIriQTWakysgJr65lc1jj6QY5ye7aFsisajotH6UhWfm/g==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/md5-js": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.2.12.tgz", + "integrity": "sha512-W/oIpHCpWU2+iAkfZYyGWE+qkpuf3vEXHLxQQDx9FPNZTTdnul0dZ2d/gUFrtQ5je1G2kp4cjG0/24YueG2LbQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/middleware-content-length": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.12.tgz", + "integrity": "sha512-YE58Yz+cvFInWI/wOTrB+DbvUVz/pLn5mC5MvOV4fdRUc6qGwygyngcucRQjAhiCEbmfLOXX0gntSIcgMvAjmA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/middleware-endpoint": { + "version": "4.4.27", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.27.tgz", + "integrity": "sha512-T3TFfUgXQlpcg+UdzcAISdZpj4Z+XECZ/cefgA6wLBd6V4lRi0svN2hBouN/be9dXQ31X4sLWz3fAQDf+nt6BA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.23.12", + "@smithy/middleware-serde": "^4.2.15", + "@smithy/node-config-provider": "^4.3.12", + "@smithy/shared-ini-file-loader": "^4.4.7", + "@smithy/types": "^4.13.1", + "@smithy/url-parser": "^4.2.12", + "@smithy/util-middleware": "^4.2.12", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/middleware-retry": { + "version": "4.4.44", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.44.tgz", + "integrity": "sha512-Y1Rav7m5CFRPQyM4CI0koD/bXjyjJu3EQxZZhtLGD88WIrBrQ7kqXM96ncd6rYnojwOo/u9MXu57JrEvu/nLrA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.12", + "@smithy/protocol-http": "^5.3.12", + "@smithy/service-error-classification": "^4.2.12", + "@smithy/smithy-client": "^4.12.7", + "@smithy/types": "^4.13.1", + "@smithy/util-middleware": "^4.2.12", + "@smithy/util-retry": "^4.2.12", + "@smithy/uuid": "^1.1.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/middleware-serde": { + "version": "4.2.15", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.15.tgz", + "integrity": "sha512-ExYhcltZSli0pgAKOpQQe1DLFBLryeZ22605y/YS+mQpdNWekum9Ujb/jMKfJKgjtz1AZldtwA/wCYuKJgjjlg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.23.12", + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/middleware-stack": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.12.tgz", + "integrity": "sha512-kruC5gRHwsCOuyCd4ouQxYjgRAym2uDlCvQ5acuMtRrcdfg7mFBg6blaxcJ09STpt3ziEkis6bhg1uwrWU7txw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/node-config-provider": { + "version": "4.3.12", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.12.tgz", + "integrity": "sha512-tr2oKX2xMcO+rBOjobSwVAkV05SIfUKz8iI53rzxEmgW3GOOPOv0UioSDk+J8OpRQnpnhsO3Af6IEBabQBVmiw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^4.2.12", + "@smithy/shared-ini-file-loader": "^4.4.7", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/node-http-handler": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.5.0.tgz", + "integrity": "sha512-Rnq9vQWiR1+/I6NZZMNzJHV6pZYyEHt2ZnuV3MG8z2NNenC4i/8Kzttz7CjZiHSmsN5frhXhg17z3Zqjjhmz1A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/abort-controller": "^4.2.12", + "@smithy/protocol-http": "^5.3.12", + "@smithy/querystring-builder": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/property-provider": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.12.tgz", + "integrity": "sha512-jqve46eYU1v7pZ5BM+fmkbq3DerkSluPr5EhvOcHxygxzD05ByDRppRwRPPpFrsFo5yDtCYLKu+kreHKVrvc7A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/protocol-http": { + "version": "5.3.12", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.12.tgz", + "integrity": "sha512-fit0GZK9I1xoRlR4jXmbLhoN0OdEpa96ul8M65XdmXnxXkuMxM0Y8HDT0Fh0Xb4I85MBvBClOzgSrV1X2s1Hxw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/querystring-builder": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.12.tgz", + "integrity": "sha512-6wTZjGABQufekycfDGMEB84BgtdOE/rCVTov+EDXQ8NHKTUNIp/j27IliwP7tjIU9LR+sSzyGBOXjeEtVgzCHg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "@smithy/util-uri-escape": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/querystring-parser": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.12.tgz", + "integrity": "sha512-P2OdvrgiAKpkPNKlKUtWbNZKB1XjPxM086NeVhK+W+wI46pIKdWBe5QyXvhUm3MEcyS/rkLvY8rZzyUdmyDZBw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/service-error-classification": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.12.tgz", + "integrity": "sha512-LlP29oSQN0Tw0b6D0Xo6BIikBswuIiGYbRACy5ujw/JgWSzTdYj46U83ssf6Ux0GyNJVivs2uReU8pt7Eu9okQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/shared-ini-file-loader": { + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.7.tgz", + "integrity": "sha512-HrOKWsUb+otTeo1HxVWeEb99t5ER1XrBi/xka2Wv6NVmTbuCUC1dvlrksdvxFtODLBjsC+PHK+fuy2x/7Ynyiw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/signature-v4": { + "version": "5.3.12", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.12.tgz", + "integrity": "sha512-B/FBwO3MVOL00DaRSXfXfa/TRXRheagt/q5A2NM13u7q+sHS59EOVGQNfG7DkmVtdQm5m3vOosoKAXSqn/OEgw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^4.2.2", + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "@smithy/util-hex-encoding": "^4.2.2", + "@smithy/util-middleware": "^4.2.12", + "@smithy/util-uri-escape": "^4.2.2", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/smithy-client": { + "version": "4.12.7", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.12.7.tgz", + "integrity": "sha512-q3gqnwml60G44FECaEEsdQMplYhDMZYCtYhMCzadCnRnnHIobZJjegmdoUo6ieLQlPUzvrMdIJUpx6DoPmzANQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.23.12", + "@smithy/middleware-endpoint": "^4.4.27", + "@smithy/middleware-stack": "^4.2.12", + "@smithy/protocol-http": "^5.3.12", + "@smithy/types": "^4.13.1", + "@smithy/util-stream": "^4.5.20", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/types": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.13.1.tgz", + "integrity": "sha512-787F3yzE2UiJIQ+wYW1CVg2odHjmaWLGksnKQHUrK/lYZSEcy1msuLVvxaR/sI2/aDe9U+TBuLsXnr3vod1g0g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/url-parser": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.12.tgz", + "integrity": "sha512-wOPKPEpso+doCZGIlr+e1lVI6+9VAKfL4kZWFgzVgGWY2hZxshNKod4l2LXS3PRC9otH/JRSjtEHqQ/7eLciRA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/querystring-parser": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/util-defaults-mode-browser": { + "version": "4.3.43", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.43.tgz", + "integrity": "sha512-Qd/0wCKMaXxev/z00TvNzGCH2jlKKKxXP1aDxB6oKwSQthe3Og2dMhSayGCnsma1bK/kQX1+X7SMP99t6FgiiQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^4.2.12", + "@smithy/smithy-client": "^4.12.7", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/util-defaults-mode-node": { + "version": "4.2.47", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.47.tgz", + "integrity": "sha512-qSRbYp1EQ7th+sPFuVcVO05AE0QH635hycdEXlpzIahqHHf2Fyd/Zl+8v0XYMJ3cgDVPa0lkMefU7oNUjAP+DQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/config-resolver": "^4.4.13", + "@smithy/credential-provider-imds": "^4.2.12", + "@smithy/node-config-provider": "^4.3.12", + "@smithy/property-provider": "^4.2.12", + "@smithy/smithy-client": "^4.12.7", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/util-endpoints": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.3.3.tgz", + "integrity": "sha512-VACQVe50j0HZPjpwWcjyT51KUQ4AnsvEaQ2lKHOSL4mNLD0G9BjEniQ+yCt1qqfKfiAHRAts26ud7hBjamrwig==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/util-middleware": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.12.tgz", + "integrity": "sha512-Er805uFUOvgc0l8nv0e0su0VFISoxhJ/AwOn3gL2NWNY2LUEldP5WtVcRYSQBcjg0y9NfG8JYrCJaYDpupBHJQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/util-retry": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.12.tgz", + "integrity": "sha512-1zopLDUEOwumjcHdJ1mwBHddubYF8GMQvstVCLC54Y46rqoHwlIU+8ZzUeaBcD+WCJHyDGSeZ2ml9YSe9aqcoQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/service-error-classification": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/util-stream": { + "version": "4.5.20", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.20.tgz", + "integrity": "sha512-4yXLm5n/B5SRBR2p8cZ90Sbv4zL4NKsgxdzCzp/83cXw2KxLEumt5p+GAVyRNZgQOSrzXn9ARpO0lUe8XSlSDw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/fetch-http-handler": "^5.3.15", + "@smithy/node-http-handler": "^4.5.0", + "@smithy/types": "^4.13.1", + "@smithy/util-base64": "^4.3.2", + "@smithy/util-buffer-from": "^4.2.2", + "@smithy/util-hex-encoding": "^4.2.2", + "@smithy/util-utf8": "^4.2.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/@smithy/util-waiter": { + "version": "4.2.13", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.13.tgz", + "integrity": "sha512-2zdZ9DTHngRtcYxJK1GUDxruNr53kv5W2Lupe0LMU+Imr6ohQg8M2T14MNkj1Y0wS3FFwpgpGQyvuaMF7CiTmQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/abort-controller": "^4.2.12", + "@smithy/types": "^4.13.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "scripts/replay-events/node_modules/fast-xml-parser": { + "version": "5.5.8", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.5.8.tgz", + "integrity": "sha512-Z7Fh2nVQSb2d+poDViM063ix2ZGt9jmY1nWhPfHBOK2Hgnb/OW3P4Et3P/81SEej0J7QbWtJqxO05h8QYfK7LQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "fast-xml-builder": "^1.1.4", + "path-expression-matcher": "^1.2.0", + "strnum": "^2.2.0" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "scripts/replay-events/node_modules/path-expression-matcher": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.2.0.tgz", + "integrity": "sha512-DwmPWeFn+tq7TiyJ2CxezCAirXjFxvaiD03npak3cRjlP9+OjTmSy1EpIrEbh+l6JgUundniloMLDQ/6VTdhLQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "scripts/utilities/letter-test-data": { "name": "nhs-notify-supplier-api-letter-test-data-utility", "version": "0.0.1", diff --git a/package.json b/package.json index 77ea9d07..92805b37 100644 --- a/package.json +++ b/package.json @@ -134,6 +134,7 @@ "pact-contracts", "scripts/utilities/*", "tests", - "tests/contracts/*" + "tests/contracts/*", + "scripts/replay-events" ] } diff --git a/scripts/replay-events/download-events.ts b/scripts/replay-events/download-events.ts new file mode 100644 index 00000000..1035a854 --- /dev/null +++ b/scripts/replay-events/download-events.ts @@ -0,0 +1,123 @@ +import { S3Client, ListObjectsV2Command, GetObjectCommand } from "@aws-sdk/client-s3"; +import { mkdir, writeFile } from "node:fs/promises"; +import * as readline from "node:readline"; +import { Readable } from "node:stream"; + +const BUCKET = process.env.BUCKET; +const PREFIX = "2026/03/"; +const MIN_NUMBER = 25; +const OUTPUT_DIR = "events-output"; + +const s3 = new S3Client({}); + +function shouldIncludeKey(key: string): boolean { + const match = key.match(/^2026\/03\/(\d+)(?:\/|$)/); + if (!match) return false; + return Number(match[1]) >= MIN_NUMBER; +} + +function keyToFilename(key: string): string { + return key.replaceAll("/", "_").replace(/\.jsonl$/, "") + ".json"; +} + +async function listMatchingKeys(): Promise { + const keys: string[] = []; + let continuationToken: string | undefined; + + do { + const resp = await s3.send( + new ListObjectsV2Command({ + Bucket: BUCKET, + Prefix: PREFIX, + ContinuationToken: continuationToken, + }) + ); + + for (const obj of resp.Contents ?? []) { + if (obj.Key && shouldIncludeKey(obj.Key)) { + keys.push(obj.Key); + } + } + + continuationToken = resp.IsTruncated ? resp.NextContinuationToken : undefined; + } while (continuationToken); + + keys.sort(); + return keys; +} + +async function* readJsonlObjects(key: string): AsyncGenerator { + const resp = await s3.send( + new GetObjectCommand({ + Bucket: BUCKET, + Key: key, + }) + ); + + if (!resp.Body) return; + + const bodyStream = + resp.Body instanceof Readable ? resp.Body : Readable.fromWeb(resp.Body as any); + + const rl = readline.createInterface({ + input: bodyStream, + crlfDelay: Infinity, + }); + + try { + for await (const rawLine of rl) { + const line = String(rawLine).trim(); + if (!line) continue; + + const outer = JSON.parse(line); + + if (outer?.Message === undefined) { + continue; + } + + const messageValue = JSON.parse(outer.Message); + + yield messageValue; + } + } finally { + rl.close(); + } +} + +async function downloadKey(key: string): Promise { + const filename = `${OUTPUT_DIR}/${keyToFilename(key)}`; + const messages: any[] = []; + + for await (const message of readJsonlObjects(key)) { + if ( + message.detail && + message.detail.type === "uk.nhs.notify.letter-rendering.letter-request.prepared.v2" && + message.detail.time >= '2026-03-26T12:00:00.000Z' && + message.detail.time <= '2026-03-27T15:10:00.000Z' + ) { + messages.push(message.detail); + } + } + if (messages.length > 0) { + await writeFile(filename, JSON.stringify(messages, null, 2) + "\n"); + console.log(`Wrote ${filename} (${messages.length} messages)`); + } +} + +async function main() { + await mkdir(OUTPUT_DIR, { recursive: true }); + + const keys = await listMatchingKeys(); + console.log(`Found ${keys.length} matching S3 objects`); + + for (const key of keys) { + await downloadKey(key); + } + + console.log(`Done — files written to ${OUTPUT_DIR}/`); +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); \ No newline at end of file diff --git a/scripts/replay-events/package.json b/scripts/replay-events/package.json new file mode 100644 index 00000000..48d5a8e4 --- /dev/null +++ b/scripts/replay-events/package.json @@ -0,0 +1,14 @@ +{ + "name": "nhs-notify-supplier-api-repla-events", + "private": true, + "dependencies": { + "@aws-sdk/client-s3": "^3.1008.0", + "@aws-sdk/client-sns": "^3.1008.0", + "tsx": "^4.20.6", + "typescript": "^5.9.3" + }, + "scripts": { + "download-events": "tsx ./download-events.ts", + "replay-events": "tsx ./replay-events.ts" + } +} \ No newline at end of file diff --git a/scripts/replay-events/replay-events.ts b/scripts/replay-events/replay-events.ts new file mode 100644 index 00000000..03d03749 --- /dev/null +++ b/scripts/replay-events/replay-events.ts @@ -0,0 +1,61 @@ +import { readdir, readFile } from "node:fs/promises"; +import { randomUUID } from "node:crypto"; +import { SNSClient, PublishBatchCommand } from "@aws-sdk/client-sns"; + +const INPUT_DIR = "events-output"; +const TOPIC_ARN = "nhs-main-supapi-eventsub"; +const BATCH_SIZE = 10; + +const sns = new SNSClient({}); + +async function publishBatch(entries: any[]): Promise { + const resp = await sns.send( + new PublishBatchCommand({ + TopicArn: TOPIC_ARN, + PublishBatchRequestEntries: entries.map((message) => ({ + Id: randomUUID(), + Message: JSON.stringify(message), + })), + }) + ); + + if (resp.Failed && resp.Failed.length > 0) { + console.error("Failed entries:", resp.Failed); + throw new Error(`${resp.Failed.length} messages failed to publish`); + } +} + +async function replayFile(filePath: string): Promise { + const messages: any[] = JSON.parse(await readFile(filePath, "utf8")); + let sent = 0; + + for (let i = 0; i < messages.length; i += BATCH_SIZE) { + const batch = messages.slice(i, i + BATCH_SIZE); + await publishBatch(batch); + sent += batch.length; + } + + return sent; +} + +async function main() { + const files = await readdir(INPUT_DIR); + + console.log(`Found ${files.length} files in ${INPUT_DIR}/`); + + let totalSent = 0; + + for (const file of files) { + const filePath = `${INPUT_DIR}/${file}`; + const sent = await replayFile(filePath); + totalSent += sent; + console.log(`Replayed ${filePath} (${sent} messages)`); + } + + console.log(`Done — sent ${totalSent} messages total`); +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); \ No newline at end of file