diff --git a/.env.example b/.env.example
index 68156c4..baae955 100644
--- a/.env.example
+++ b/.env.example
@@ -28,3 +28,18 @@ EMAIL_TEMPLATES_DIR=src/email/templates
# Form Schemas Directory
FORM_SCHEMAS_DIR=schemas
+
+# EZPay Configuration
+EZPAY_API_KEY=HWqgTn5EXIHLAzVjXtGpB2mIjgQgj0Ql
+EZPAY_BASE_URL=https://test.ezpay.gov.bb
+EZPAY_WEBHOOK_SECRET=your_webhook_secret
+
+# Department-specific EZPay API keys
+EZPAY_EDUCATION_API_KEY=edu_specific_api_key_here
+EZPAY_HEALTH_API_KEY=health_specific_api_key_here
+EZPAY_SOCIAL_SERVICES_API_KEY=social_services_api_key_here
+EZPAY_TRANSPORT_API_KEY=transport_api_key_here
+
+# Form-specific secrets (example)
+PRIMARY_SCHOOL_TEXTBOOK_GRANT_PAYMENT_CODE=EDU001
+PRIMARY_SCHOOL_TEXTBOOK_GRANT_ADMIN_EMAIL=education@gov.bb
diff --git a/package-lock.json b/package-lock.json
index 8ecfcb5..890e7e6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,8 +9,11 @@
"version": "0.0.1",
"license": "UNLICENSED",
"dependencies": {
+ "@aws-sdk/client-s3": "^3.954.0",
"@aws-sdk/client-ses": "^3.933.0",
"@aws-sdk/client-sesv2": "^3.933.0",
+ "@aws-sdk/lib-storage": "^3.954.0",
+ "@aws-sdk/s3-request-presigner": "^3.954.0",
"@nestjs/common": "^9.0.0",
"@nestjs/config": "^4.0.2",
"@nestjs/core": "^9.0.0",
@@ -33,6 +36,7 @@
"@nestjs/testing": "^9.0.0",
"@types/express": "^4.17.13",
"@types/jest": "28.1.8",
+ "@types/multer": "^2.0.0",
"@types/node": "^16.0.0",
"@types/supertest": "^2.0.11",
"@types/uuid": "^11.0.0",
@@ -163,6 +167,92 @@
"tslib": "^2.1.0"
}
},
+ "node_modules/@aws-crypto/crc32": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz",
+ "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==",
+ "dependencies": {
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/crc32/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/@aws-crypto/crc32c": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz",
+ "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==",
+ "dependencies": {
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-crypto/crc32c/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/@aws-crypto/sha1-browser": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz",
+ "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==",
+ "dependencies": {
+ "@aws-crypto/supports-web-crypto": "^5.2.0",
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "@aws-sdk/util-locate-window": "^3.0.0",
+ "@smithy/util-utf8": "^2.0.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/is-array-buffer": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
+ "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-buffer-from": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
+ "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-utf8": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
+ "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/sha1-browser/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
"node_modules/@aws-crypto/sha256-browser": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz",
@@ -298,6 +388,543 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
+ "node_modules/@aws-sdk/client-s3": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.954.0.tgz",
+ "integrity": "sha512-DoeySsljzjuWRzqoETLszHGKKOOWlzuGZh3oAF7TkYRsrwbuYYmttrWomb9koogaF0S5YSPwCMCUbKbpF0lbTA==",
+ "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.954.0",
+ "@aws-sdk/credential-provider-node": "3.954.0",
+ "@aws-sdk/middleware-bucket-endpoint": "3.953.0",
+ "@aws-sdk/middleware-expect-continue": "3.953.0",
+ "@aws-sdk/middleware-flexible-checksums": "3.954.0",
+ "@aws-sdk/middleware-host-header": "3.953.0",
+ "@aws-sdk/middleware-location-constraint": "3.953.0",
+ "@aws-sdk/middleware-logger": "3.953.0",
+ "@aws-sdk/middleware-recursion-detection": "3.953.0",
+ "@aws-sdk/middleware-sdk-s3": "3.954.0",
+ "@aws-sdk/middleware-ssec": "3.953.0",
+ "@aws-sdk/middleware-user-agent": "3.954.0",
+ "@aws-sdk/region-config-resolver": "3.953.0",
+ "@aws-sdk/signature-v4-multi-region": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/util-endpoints": "3.953.0",
+ "@aws-sdk/util-user-agent-browser": "3.953.0",
+ "@aws-sdk/util-user-agent-node": "3.954.0",
+ "@smithy/config-resolver": "^4.4.4",
+ "@smithy/core": "^3.19.0",
+ "@smithy/eventstream-serde-browser": "^4.2.6",
+ "@smithy/eventstream-serde-config-resolver": "^4.3.6",
+ "@smithy/eventstream-serde-node": "^4.2.6",
+ "@smithy/fetch-http-handler": "^5.3.7",
+ "@smithy/hash-blob-browser": "^4.2.7",
+ "@smithy/hash-node": "^4.2.6",
+ "@smithy/hash-stream-node": "^4.2.6",
+ "@smithy/invalid-dependency": "^4.2.6",
+ "@smithy/md5-js": "^4.2.6",
+ "@smithy/middleware-content-length": "^4.2.6",
+ "@smithy/middleware-endpoint": "^4.4.0",
+ "@smithy/middleware-retry": "^4.4.16",
+ "@smithy/middleware-serde": "^4.2.7",
+ "@smithy/middleware-stack": "^4.2.6",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/node-http-handler": "^4.4.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/smithy-client": "^4.10.1",
+ "@smithy/types": "^4.10.0",
+ "@smithy/url-parser": "^4.2.6",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-body-length-browser": "^4.2.0",
+ "@smithy/util-body-length-node": "^4.2.1",
+ "@smithy/util-defaults-mode-browser": "^4.3.15",
+ "@smithy/util-defaults-mode-node": "^4.2.18",
+ "@smithy/util-endpoints": "^3.2.6",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-retry": "^4.2.6",
+ "@smithy/util-stream": "^4.5.7",
+ "@smithy/util-utf8": "^4.2.0",
+ "@smithy/util-waiter": "^4.2.6",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/client-sso": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.954.0.tgz",
+ "integrity": "sha512-FVyMAvlFhLK68DHWB1lSkCRTm25xl38bIZDd+jKt5+yDolCrG5+n9aIN8AA8jNO1HNGhZuMjSIQm9r5rGmJH8g==",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "3.954.0",
+ "@aws-sdk/middleware-host-header": "3.953.0",
+ "@aws-sdk/middleware-logger": "3.953.0",
+ "@aws-sdk/middleware-recursion-detection": "3.953.0",
+ "@aws-sdk/middleware-user-agent": "3.954.0",
+ "@aws-sdk/region-config-resolver": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/util-endpoints": "3.953.0",
+ "@aws-sdk/util-user-agent-browser": "3.953.0",
+ "@aws-sdk/util-user-agent-node": "3.954.0",
+ "@smithy/config-resolver": "^4.4.4",
+ "@smithy/core": "^3.19.0",
+ "@smithy/fetch-http-handler": "^5.3.7",
+ "@smithy/hash-node": "^4.2.6",
+ "@smithy/invalid-dependency": "^4.2.6",
+ "@smithy/middleware-content-length": "^4.2.6",
+ "@smithy/middleware-endpoint": "^4.4.0",
+ "@smithy/middleware-retry": "^4.4.16",
+ "@smithy/middleware-serde": "^4.2.7",
+ "@smithy/middleware-stack": "^4.2.6",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/node-http-handler": "^4.4.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/smithy-client": "^4.10.1",
+ "@smithy/types": "^4.10.0",
+ "@smithy/url-parser": "^4.2.6",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-body-length-browser": "^4.2.0",
+ "@smithy/util-body-length-node": "^4.2.1",
+ "@smithy/util-defaults-mode-browser": "^4.3.15",
+ "@smithy/util-defaults-mode-node": "^4.2.18",
+ "@smithy/util-endpoints": "^3.2.6",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-retry": "^4.2.6",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/core": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.954.0.tgz",
+ "integrity": "sha512-5oYO5RP+mvCNXNj8XnF9jZo0EP0LTseYOJVNQYcii1D9DJqzHL3HJWurYh7cXxz7G7eDyvVYA01O9Xpt34TdoA==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/xml-builder": "3.953.0",
+ "@smithy/core": "^3.19.0",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/signature-v4": "^5.3.6",
+ "@smithy/smithy-client": "^4.10.1",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-env": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.954.0.tgz",
+ "integrity": "sha512-2HNkqBjfsvyoRuPAiFh86JBFMFyaCNhL4VyH6XqwTGKZffjG7hdBmzXPy7AT7G3oFh1k/1Zc27v0qxaKoK7mBA==",
+ "dependencies": {
+ "@aws-sdk/core": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-http": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.954.0.tgz",
+ "integrity": "sha512-CrWD5300+NE1OYRnSVDxoG7G0b5cLIZb7yp+rNQ5Jq/kqnTmyJXpVAsivq+bQIDaGzPXhadzpAMIoo7K/aHaag==",
+ "dependencies": {
+ "@aws-sdk/core": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/fetch-http-handler": "^5.3.7",
+ "@smithy/node-http-handler": "^4.4.6",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/smithy-client": "^4.10.1",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-stream": "^4.5.7",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-ini": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.954.0.tgz",
+ "integrity": "sha512-WAFD8pVwRSoBsuXcoD+s/hrdsP9Z0PNUedSgkOGExuJVAabpM2cIIMzYNsdHio9XFZUSqHkv8mF5mQXuIZvuzg==",
+ "dependencies": {
+ "@aws-sdk/core": "3.954.0",
+ "@aws-sdk/credential-provider-env": "3.954.0",
+ "@aws-sdk/credential-provider-http": "3.954.0",
+ "@aws-sdk/credential-provider-login": "3.954.0",
+ "@aws-sdk/credential-provider-process": "3.954.0",
+ "@aws-sdk/credential-provider-sso": "3.954.0",
+ "@aws-sdk/credential-provider-web-identity": "3.954.0",
+ "@aws-sdk/nested-clients": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/credential-provider-imds": "^4.2.6",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/shared-ini-file-loader": "^4.4.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-node": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.954.0.tgz",
+ "integrity": "sha512-UPBjw7Lnly5i+/rES8Z5U+nPaumzEUYOE/wrHkxyH6JjwFWn8w7R07fE5Z5cgYlIq1U1lQ7sxYwB3wHPpQ65Aw==",
+ "dependencies": {
+ "@aws-sdk/credential-provider-env": "3.954.0",
+ "@aws-sdk/credential-provider-http": "3.954.0",
+ "@aws-sdk/credential-provider-ini": "3.954.0",
+ "@aws-sdk/credential-provider-process": "3.954.0",
+ "@aws-sdk/credential-provider-sso": "3.954.0",
+ "@aws-sdk/credential-provider-web-identity": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/credential-provider-imds": "^4.2.6",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/shared-ini-file-loader": "^4.4.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-process": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.954.0.tgz",
+ "integrity": "sha512-Y1/0O2LgbKM8iIgcVj/GNEQW6p90LVTCOzF2CI1pouoKqxmZ/1F7F66WHoa6XUOfKaCRj/R6nuMR3om9ThaM5A==",
+ "dependencies": {
+ "@aws-sdk/core": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/shared-ini-file-loader": "^4.4.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-sso": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.954.0.tgz",
+ "integrity": "sha512-UXxGfkp/plFRdyidMLvNul5zoLKmHhVQOCrD2OgR/lg9jNqNmJ7abF+Qu8abo902iDkhU21Qj4M398cx6l8Kng==",
+ "dependencies": {
+ "@aws-sdk/client-sso": "3.954.0",
+ "@aws-sdk/core": "3.954.0",
+ "@aws-sdk/token-providers": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/shared-ini-file-loader": "^4.4.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-web-identity": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.954.0.tgz",
+ "integrity": "sha512-XEyf1T08q1tG4zkTS4Dnf1cAQyrJUo/xlvi6XNpqGhY3bOmKUYE2h/K6eITIdytDL9VuCpWYQ6YRcIVtL29E0w==",
+ "dependencies": {
+ "@aws-sdk/core": "3.954.0",
+ "@aws-sdk/nested-clients": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/shared-ini-file-loader": "^4.4.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-host-header": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.953.0.tgz",
+ "integrity": "sha512-jTGhfkONav+r4E6HLOrl5SzBqDmPByUYCkyB/c/3TVb8jX3wAZx8/q9bphKpCh+G5ARi3IdbSisgkZrJYqQ19Q==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-logger": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.953.0.tgz",
+ "integrity": "sha512-PlWdVYgcuptkIC0ZKqVUhWNtSHXJSx7U9V8J7dJjRmsXC40X7zpEycvrkzDMJjeTDGcCceYbyYAg/4X1lkcIMw==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-recursion-detection": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.953.0.tgz",
+ "integrity": "sha512-cmIJx0gWeesUKK4YwgE+VQL3mpACr3/J24fbwnc1Z5tntC86b+HQFzU5vsBDw6lLwyD46dBgWdsXFh1jL+ZaFw==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@aws/lambda-invoke-store": "^0.2.2",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-sdk-s3": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.954.0.tgz",
+ "integrity": "sha512-274CNmnRjknmfFb2o0Azxic54fnujaA8AYSeRUOho3lN48TVzx85eAFWj2kLgvUJO88pE3jBDPWboKQiQdXeUQ==",
+ "dependencies": {
+ "@aws-sdk/core": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/util-arn-parser": "3.953.0",
+ "@smithy/core": "^3.19.0",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/signature-v4": "^5.3.6",
+ "@smithy/smithy-client": "^4.10.1",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-config-provider": "^4.2.0",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-stream": "^4.5.7",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-user-agent": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.954.0.tgz",
+ "integrity": "sha512-5PX8JDe3dB2+MqXeGIhmgFnm2rbVsSxhz+Xyuu1oxLtbOn+a9UDA+sNBufEBjt3UxWy5qwEEY1fxdbXXayjlGg==",
+ "dependencies": {
+ "@aws-sdk/core": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/util-endpoints": "3.953.0",
+ "@smithy/core": "^3.19.0",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/nested-clients": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.954.0.tgz",
+ "integrity": "sha512-JLUhf35fTQIDPLk6G5KPggL9tV//Hjhy6+N2zZeis76LuBRNhKDq8z1CFyKhjf00vXi/tDYdn9D7y9emI+5Y/g==",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "3.954.0",
+ "@aws-sdk/middleware-host-header": "3.953.0",
+ "@aws-sdk/middleware-logger": "3.953.0",
+ "@aws-sdk/middleware-recursion-detection": "3.953.0",
+ "@aws-sdk/middleware-user-agent": "3.954.0",
+ "@aws-sdk/region-config-resolver": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/util-endpoints": "3.953.0",
+ "@aws-sdk/util-user-agent-browser": "3.953.0",
+ "@aws-sdk/util-user-agent-node": "3.954.0",
+ "@smithy/config-resolver": "^4.4.4",
+ "@smithy/core": "^3.19.0",
+ "@smithy/fetch-http-handler": "^5.3.7",
+ "@smithy/hash-node": "^4.2.6",
+ "@smithy/invalid-dependency": "^4.2.6",
+ "@smithy/middleware-content-length": "^4.2.6",
+ "@smithy/middleware-endpoint": "^4.4.0",
+ "@smithy/middleware-retry": "^4.4.16",
+ "@smithy/middleware-serde": "^4.2.7",
+ "@smithy/middleware-stack": "^4.2.6",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/node-http-handler": "^4.4.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/smithy-client": "^4.10.1",
+ "@smithy/types": "^4.10.0",
+ "@smithy/url-parser": "^4.2.6",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-body-length-browser": "^4.2.0",
+ "@smithy/util-body-length-node": "^4.2.1",
+ "@smithy/util-defaults-mode-browser": "^4.3.15",
+ "@smithy/util-defaults-mode-node": "^4.2.18",
+ "@smithy/util-endpoints": "^3.2.6",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-retry": "^4.2.6",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/region-config-resolver": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.953.0.tgz",
+ "integrity": "sha512-5MJgnsc+HLO+le0EK1cy92yrC7kyhGZSpaq8PcQvKs9qtXCXT5Tb6tMdkr5Y07JxYsYOV1omWBynvL6PWh08tQ==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/config-resolver": "^4.4.4",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/signature-v4-multi-region": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.954.0.tgz",
+ "integrity": "sha512-GJJbUaSlGrMSRWui3Oz8ByygpQlzDGm195yTKirgGyu4tfYrFr/QWrWT42EUktY/L4Irev1pdHTuLS+AGHO1gw==",
+ "dependencies": {
+ "@aws-sdk/middleware-sdk-s3": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/signature-v4": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/token-providers": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.954.0.tgz",
+ "integrity": "sha512-rDyN3oQQKMOJgyQ9/LNbh4fAGAj8ePMGOAQzSP/kyzizmViI6STpBW1o/VRqiTgMNi1bvA9ZasDtfrJqcVt0iA==",
+ "dependencies": {
+ "@aws-sdk/core": "3.954.0",
+ "@aws-sdk/nested-clients": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/shared-ini-file-loader": "^4.4.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/types": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.953.0.tgz",
+ "integrity": "sha512-M9Iwg9kTyqTErI0vOTVVpcnTHWzS3VplQppy8MuL02EE+mJ0BIwpWfsaAPQW+/XnVpdNpWZTsHcNE29f1+hR8g==",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/util-arn-parser": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.953.0.tgz",
+ "integrity": "sha512-9hqdKkn4OvYzzaLryq2xnwcrPc8ziY34i9szUdgBfSqEC6pBxbY9/lLXmrgzfwMSL2Z7/v2go4Od0p5eukKLMQ==",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/util-endpoints": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.953.0.tgz",
+ "integrity": "sha512-rjaS6jrFksopXvNg6YeN+D1lYwhcByORNlFuYesFvaQNtPOufbE5tJL4GJ3TMXyaY0uFR28N5BHHITPyWWfH/g==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/types": "^4.10.0",
+ "@smithy/url-parser": "^4.2.6",
+ "@smithy/util-endpoints": "^3.2.6",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/util-user-agent-browser": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.953.0.tgz",
+ "integrity": "sha512-UF5NeqYesWuFao+u7LJvpV1SJCaLml5BtFZKUdTnNNMeN6jvV+dW/eQoFGpXF94RCqguX0XESmRuRRPQp+/rzQ==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/types": "^4.10.0",
+ "bowser": "^2.11.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/util-user-agent-node": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.954.0.tgz",
+ "integrity": "sha512-fB5S5VOu7OFkeNzcblQlez4AjO5hgDFaa7phYt7716YWisY3RjAaQPlxgv+G3GltHHDJIfzEC5aRxdf62B9zMg==",
+ "dependencies": {
+ "@aws-sdk/middleware-user-agent": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "aws-crt": ">=1.0.0"
+ },
+ "peerDependenciesMeta": {
+ "aws-crt": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/xml-builder": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.953.0.tgz",
+ "integrity": "sha512-Zmrj21jQ2OeOJGr9spPiN00aQvXa/WUqRXcTVENhrMt+OFoSOfDFpYhUj9NQ09QmQ8KMWFoWuWW6iKurNqLvAA==",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "fast-xml-parser": "5.2.5",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
"node_modules/@aws-sdk/client-ses": {
"version": "3.933.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-ses/-/client-ses-3.933.0.tgz",
@@ -504,60 +1131,302 @@
"node": ">=18.0.0"
}
},
- "node_modules/@aws-sdk/credential-provider-env/node_modules/tslib": {
- "version": "2.8.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
- "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ "node_modules/@aws-sdk/credential-provider-env/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/@aws-sdk/credential-provider-http": {
+ "version": "3.932.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.932.0.tgz",
+ "integrity": "sha512-b6N9Nnlg8JInQwzBkUq5spNaXssM3h3zLxGzpPrnw0nHSIWPJPTbZzA5Ca285fcDUFuKP+qf3qkuqlAjGOdWhg==",
+ "dependencies": {
+ "@aws-sdk/core": "3.932.0",
+ "@aws-sdk/types": "3.930.0",
+ "@smithy/fetch-http-handler": "^5.3.6",
+ "@smithy/node-http-handler": "^4.4.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/smithy-client": "^4.9.5",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-stream": "^4.5.6",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-http/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/@aws-sdk/credential-provider-ini": {
+ "version": "3.933.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.933.0.tgz",
+ "integrity": "sha512-HygGyKuMG5AaGXsmM0d81miWDon55xwalRHB3UmDg3QBhtunbNIoIaWUbNTKuBZXcIN6emeeEZw/YgSMqLc0YA==",
+ "dependencies": {
+ "@aws-sdk/core": "3.932.0",
+ "@aws-sdk/credential-provider-env": "3.932.0",
+ "@aws-sdk/credential-provider-http": "3.932.0",
+ "@aws-sdk/credential-provider-process": "3.932.0",
+ "@aws-sdk/credential-provider-sso": "3.933.0",
+ "@aws-sdk/credential-provider-web-identity": "3.933.0",
+ "@aws-sdk/nested-clients": "3.933.0",
+ "@aws-sdk/types": "3.930.0",
+ "@smithy/credential-provider-imds": "^4.2.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/shared-ini-file-loader": "^4.4.0",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-ini/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/@aws-sdk/credential-provider-login": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.954.0.tgz",
+ "integrity": "sha512-EYqaBWwdVbVK7prmsmgTWLPptoWREplPkFMFscOpVmseDvf/0IjYNbNLLtfuhy/6L7ZBGI9wat2k4u0MRivvxA==",
+ "dependencies": {
+ "@aws-sdk/core": "3.954.0",
+ "@aws-sdk/nested-clients": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/shared-ini-file-loader": "^4.4.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/core": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.954.0.tgz",
+ "integrity": "sha512-5oYO5RP+mvCNXNj8XnF9jZo0EP0LTseYOJVNQYcii1D9DJqzHL3HJWurYh7cXxz7G7eDyvVYA01O9Xpt34TdoA==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/xml-builder": "3.953.0",
+ "@smithy/core": "^3.19.0",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/signature-v4": "^5.3.6",
+ "@smithy/smithy-client": "^4.10.1",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/middleware-host-header": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.953.0.tgz",
+ "integrity": "sha512-jTGhfkONav+r4E6HLOrl5SzBqDmPByUYCkyB/c/3TVb8jX3wAZx8/q9bphKpCh+G5ARi3IdbSisgkZrJYqQ19Q==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/middleware-logger": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.953.0.tgz",
+ "integrity": "sha512-PlWdVYgcuptkIC0ZKqVUhWNtSHXJSx7U9V8J7dJjRmsXC40X7zpEycvrkzDMJjeTDGcCceYbyYAg/4X1lkcIMw==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/middleware-recursion-detection": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.953.0.tgz",
+ "integrity": "sha512-cmIJx0gWeesUKK4YwgE+VQL3mpACr3/J24fbwnc1Z5tntC86b+HQFzU5vsBDw6lLwyD46dBgWdsXFh1jL+ZaFw==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@aws/lambda-invoke-store": "^0.2.2",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/middleware-user-agent": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.954.0.tgz",
+ "integrity": "sha512-5PX8JDe3dB2+MqXeGIhmgFnm2rbVsSxhz+Xyuu1oxLtbOn+a9UDA+sNBufEBjt3UxWy5qwEEY1fxdbXXayjlGg==",
+ "dependencies": {
+ "@aws-sdk/core": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/util-endpoints": "3.953.0",
+ "@smithy/core": "^3.19.0",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/nested-clients": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.954.0.tgz",
+ "integrity": "sha512-JLUhf35fTQIDPLk6G5KPggL9tV//Hjhy6+N2zZeis76LuBRNhKDq8z1CFyKhjf00vXi/tDYdn9D7y9emI+5Y/g==",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "3.954.0",
+ "@aws-sdk/middleware-host-header": "3.953.0",
+ "@aws-sdk/middleware-logger": "3.953.0",
+ "@aws-sdk/middleware-recursion-detection": "3.953.0",
+ "@aws-sdk/middleware-user-agent": "3.954.0",
+ "@aws-sdk/region-config-resolver": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/util-endpoints": "3.953.0",
+ "@aws-sdk/util-user-agent-browser": "3.953.0",
+ "@aws-sdk/util-user-agent-node": "3.954.0",
+ "@smithy/config-resolver": "^4.4.4",
+ "@smithy/core": "^3.19.0",
+ "@smithy/fetch-http-handler": "^5.3.7",
+ "@smithy/hash-node": "^4.2.6",
+ "@smithy/invalid-dependency": "^4.2.6",
+ "@smithy/middleware-content-length": "^4.2.6",
+ "@smithy/middleware-endpoint": "^4.4.0",
+ "@smithy/middleware-retry": "^4.4.16",
+ "@smithy/middleware-serde": "^4.2.7",
+ "@smithy/middleware-stack": "^4.2.6",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/node-http-handler": "^4.4.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/smithy-client": "^4.10.1",
+ "@smithy/types": "^4.10.0",
+ "@smithy/url-parser": "^4.2.6",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-body-length-browser": "^4.2.0",
+ "@smithy/util-body-length-node": "^4.2.1",
+ "@smithy/util-defaults-mode-browser": "^4.3.15",
+ "@smithy/util-defaults-mode-node": "^4.2.18",
+ "@smithy/util-endpoints": "^3.2.6",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-retry": "^4.2.6",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/region-config-resolver": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.953.0.tgz",
+ "integrity": "sha512-5MJgnsc+HLO+le0EK1cy92yrC7kyhGZSpaq8PcQvKs9qtXCXT5Tb6tMdkr5Y07JxYsYOV1omWBynvL6PWh08tQ==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/config-resolver": "^4.4.4",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/types": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.953.0.tgz",
+ "integrity": "sha512-M9Iwg9kTyqTErI0vOTVVpcnTHWzS3VplQppy8MuL02EE+mJ0BIwpWfsaAPQW+/XnVpdNpWZTsHcNE29f1+hR8g==",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/util-endpoints": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.953.0.tgz",
+ "integrity": "sha512-rjaS6jrFksopXvNg6YeN+D1lYwhcByORNlFuYesFvaQNtPOufbE5tJL4GJ3TMXyaY0uFR28N5BHHITPyWWfH/g==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/types": "^4.10.0",
+ "@smithy/url-parser": "^4.2.6",
+ "@smithy/util-endpoints": "^3.2.6",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/util-user-agent-browser": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.953.0.tgz",
+ "integrity": "sha512-UF5NeqYesWuFao+u7LJvpV1SJCaLml5BtFZKUdTnNNMeN6jvV+dW/eQoFGpXF94RCqguX0XESmRuRRPQp+/rzQ==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/types": "^4.10.0",
+ "bowser": "^2.11.0",
+ "tslib": "^2.6.2"
+ }
},
- "node_modules/@aws-sdk/credential-provider-http": {
- "version": "3.932.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.932.0.tgz",
- "integrity": "sha512-b6N9Nnlg8JInQwzBkUq5spNaXssM3h3zLxGzpPrnw0nHSIWPJPTbZzA5Ca285fcDUFuKP+qf3qkuqlAjGOdWhg==",
+ "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/util-user-agent-node": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.954.0.tgz",
+ "integrity": "sha512-fB5S5VOu7OFkeNzcblQlez4AjO5hgDFaa7phYt7716YWisY3RjAaQPlxgv+G3GltHHDJIfzEC5aRxdf62B9zMg==",
"dependencies": {
- "@aws-sdk/core": "3.932.0",
- "@aws-sdk/types": "3.930.0",
- "@smithy/fetch-http-handler": "^5.3.6",
- "@smithy/node-http-handler": "^4.4.5",
- "@smithy/property-provider": "^4.2.5",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/smithy-client": "^4.9.5",
- "@smithy/types": "^4.9.0",
- "@smithy/util-stream": "^4.5.6",
+ "@aws-sdk/middleware-user-agent": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/types": "^4.10.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "aws-crt": ">=1.0.0"
+ },
+ "peerDependenciesMeta": {
+ "aws-crt": {
+ "optional": true
+ }
}
},
- "node_modules/@aws-sdk/credential-provider-http/node_modules/tslib": {
- "version": "2.8.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
- "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
- },
- "node_modules/@aws-sdk/credential-provider-ini": {
- "version": "3.933.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.933.0.tgz",
- "integrity": "sha512-HygGyKuMG5AaGXsmM0d81miWDon55xwalRHB3UmDg3QBhtunbNIoIaWUbNTKuBZXcIN6emeeEZw/YgSMqLc0YA==",
+ "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/xml-builder": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.953.0.tgz",
+ "integrity": "sha512-Zmrj21jQ2OeOJGr9spPiN00aQvXa/WUqRXcTVENhrMt+OFoSOfDFpYhUj9NQ09QmQ8KMWFoWuWW6iKurNqLvAA==",
"dependencies": {
- "@aws-sdk/core": "3.932.0",
- "@aws-sdk/credential-provider-env": "3.932.0",
- "@aws-sdk/credential-provider-http": "3.932.0",
- "@aws-sdk/credential-provider-process": "3.932.0",
- "@aws-sdk/credential-provider-sso": "3.933.0",
- "@aws-sdk/credential-provider-web-identity": "3.933.0",
- "@aws-sdk/nested-clients": "3.933.0",
- "@aws-sdk/types": "3.930.0",
- "@smithy/credential-provider-imds": "^4.2.5",
- "@smithy/property-provider": "^4.2.5",
- "@smithy/shared-ini-file-loader": "^4.4.0",
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.10.0",
+ "fast-xml-parser": "5.2.5",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18.0.0"
}
},
- "node_modules/@aws-sdk/credential-provider-ini/node_modules/tslib": {
+ "node_modules/@aws-sdk/credential-provider-login/node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
@@ -655,6 +1524,192 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
+ "node_modules/@aws-sdk/lib-storage": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.954.0.tgz",
+ "integrity": "sha512-NdqDWorjG5dvnp/sfDsrru5S52O8gCKo92wcQe8A7M+6JUaQ6Qtnmzh7104SYCc/OdZwrjg7OL1pViGfw+lZxQ==",
+ "dependencies": {
+ "@smithy/abort-controller": "^4.2.6",
+ "@smithy/middleware-endpoint": "^4.4.0",
+ "@smithy/smithy-client": "^4.10.1",
+ "buffer": "5.6.0",
+ "events": "3.3.0",
+ "stream-browserify": "3.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@aws-sdk/client-s3": "^3.954.0"
+ }
+ },
+ "node_modules/@aws-sdk/lib-storage/node_modules/buffer": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz",
+ "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==",
+ "dependencies": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4"
+ }
+ },
+ "node_modules/@aws-sdk/lib-storage/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/@aws-sdk/middleware-bucket-endpoint": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.953.0.tgz",
+ "integrity": "sha512-YHVRIOowtGIl/L2WuS83FgRlm31tU0aL1yryWaFtF+AFjA5BIeiFkxIZqaRGxJpJvFEBdohsyq6Ipv5mgWfezg==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/util-arn-parser": "3.953.0",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-config-provider": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/@aws-sdk/types": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.953.0.tgz",
+ "integrity": "sha512-M9Iwg9kTyqTErI0vOTVVpcnTHWzS3VplQppy8MuL02EE+mJ0BIwpWfsaAPQW+/XnVpdNpWZTsHcNE29f1+hR8g==",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/@aws-sdk/util-arn-parser": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.953.0.tgz",
+ "integrity": "sha512-9hqdKkn4OvYzzaLryq2xnwcrPc8ziY34i9szUdgBfSqEC6pBxbY9/lLXmrgzfwMSL2Z7/v2go4Od0p5eukKLMQ==",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/@aws-sdk/middleware-expect-continue": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.953.0.tgz",
+ "integrity": "sha512-BQTVXrypQ0rbb7au/Hk4IS5GaJZlwk6O44Rjk6Kxb0IvGQhSurNTuesFiJx1sLbf+w+T31saPtODcfQQERqhCQ==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-expect-continue/node_modules/@aws-sdk/types": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.953.0.tgz",
+ "integrity": "sha512-M9Iwg9kTyqTErI0vOTVVpcnTHWzS3VplQppy8MuL02EE+mJ0BIwpWfsaAPQW+/XnVpdNpWZTsHcNE29f1+hR8g==",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-expect-continue/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/@aws-sdk/middleware-flexible-checksums": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.954.0.tgz",
+ "integrity": "sha512-hHOPDJyxucNodkgapLhA0VdwDBwVYN9DX20aA6j+3nwutAlZ5skaV7Bw0W3YC7Fh/ieDKKhcSZulONd4lVTwMg==",
+ "dependencies": {
+ "@aws-crypto/crc32": "5.2.0",
+ "@aws-crypto/crc32c": "5.2.0",
+ "@aws-crypto/util": "5.2.0",
+ "@aws-sdk/core": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/is-array-buffer": "^4.2.0",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-stream": "^4.5.7",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@aws-sdk/core": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.954.0.tgz",
+ "integrity": "sha512-5oYO5RP+mvCNXNj8XnF9jZo0EP0LTseYOJVNQYcii1D9DJqzHL3HJWurYh7cXxz7G7eDyvVYA01O9Xpt34TdoA==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/xml-builder": "3.953.0",
+ "@smithy/core": "^3.19.0",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/signature-v4": "^5.3.6",
+ "@smithy/smithy-client": "^4.10.1",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@aws-sdk/types": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.953.0.tgz",
+ "integrity": "sha512-M9Iwg9kTyqTErI0vOTVVpcnTHWzS3VplQppy8MuL02EE+mJ0BIwpWfsaAPQW+/XnVpdNpWZTsHcNE29f1+hR8g==",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@aws-sdk/xml-builder": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.953.0.tgz",
+ "integrity": "sha512-Zmrj21jQ2OeOJGr9spPiN00aQvXa/WUqRXcTVENhrMt+OFoSOfDFpYhUj9NQ09QmQ8KMWFoWuWW6iKurNqLvAA==",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "fast-xml-parser": "5.2.5",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
"node_modules/@aws-sdk/middleware-host-header": {
"version": "3.930.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.930.0.tgz",
@@ -674,6 +1729,36 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
+ "node_modules/@aws-sdk/middleware-location-constraint": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.953.0.tgz",
+ "integrity": "sha512-h0urrbteIQEybyIISaJfQLZ/+/lJPRzPWAQT4epvzfgv/4MKZI7K83dK7SfTwAooVKFBHiCMok2Cf0iHDt07Kw==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-location-constraint/node_modules/@aws-sdk/types": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.953.0.tgz",
+ "integrity": "sha512-M9Iwg9kTyqTErI0vOTVVpcnTHWzS3VplQppy8MuL02EE+mJ0BIwpWfsaAPQW+/XnVpdNpWZTsHcNE29f1+hR8g==",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-location-constraint/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
"node_modules/@aws-sdk/middleware-logger": {
"version": "3.930.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.930.0.tgz",
@@ -741,6 +1826,36 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
+ "node_modules/@aws-sdk/middleware-ssec": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.953.0.tgz",
+ "integrity": "sha512-OrhG1kcQ9zZh3NS3RovR028N0+UndQ957zF1k5HPLeFLwFwQN1uPOufzzPzAyXIIKtR69ARFsQI4mstZS4DMvw==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-ssec/node_modules/@aws-sdk/types": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.953.0.tgz",
+ "integrity": "sha512-M9Iwg9kTyqTErI0vOTVVpcnTHWzS3VplQppy8MuL02EE+mJ0BIwpWfsaAPQW+/XnVpdNpWZTsHcNE29f1+hR8g==",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-ssec/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
"node_modules/@aws-sdk/middleware-user-agent": {
"version": "3.932.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.932.0.tgz",
@@ -836,6 +1951,128 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
+ "node_modules/@aws-sdk/s3-request-presigner": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.954.0.tgz",
+ "integrity": "sha512-ypFOt8JK/x6p2hD9Jd5ctStw8h32KdgSBV+eXAMvcMP4DFt7wp6f7StwbjAblehZnPwNolFJE4Hz2F08nh4VdA==",
+ "dependencies": {
+ "@aws-sdk/signature-v4-multi-region": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/util-format-url": "3.953.0",
+ "@smithy/middleware-endpoint": "^4.4.0",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/smithy-client": "^4.10.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/s3-request-presigner/node_modules/@aws-sdk/core": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.954.0.tgz",
+ "integrity": "sha512-5oYO5RP+mvCNXNj8XnF9jZo0EP0LTseYOJVNQYcii1D9DJqzHL3HJWurYh7cXxz7G7eDyvVYA01O9Xpt34TdoA==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/xml-builder": "3.953.0",
+ "@smithy/core": "^3.19.0",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/signature-v4": "^5.3.6",
+ "@smithy/smithy-client": "^4.10.1",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/s3-request-presigner/node_modules/@aws-sdk/middleware-sdk-s3": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.954.0.tgz",
+ "integrity": "sha512-274CNmnRjknmfFb2o0Azxic54fnujaA8AYSeRUOho3lN48TVzx85eAFWj2kLgvUJO88pE3jBDPWboKQiQdXeUQ==",
+ "dependencies": {
+ "@aws-sdk/core": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/util-arn-parser": "3.953.0",
+ "@smithy/core": "^3.19.0",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/signature-v4": "^5.3.6",
+ "@smithy/smithy-client": "^4.10.1",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-config-provider": "^4.2.0",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-stream": "^4.5.7",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/s3-request-presigner/node_modules/@aws-sdk/signature-v4-multi-region": {
+ "version": "3.954.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.954.0.tgz",
+ "integrity": "sha512-GJJbUaSlGrMSRWui3Oz8ByygpQlzDGm195yTKirgGyu4tfYrFr/QWrWT42EUktY/L4Irev1pdHTuLS+AGHO1gw==",
+ "dependencies": {
+ "@aws-sdk/middleware-sdk-s3": "3.954.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/signature-v4": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/s3-request-presigner/node_modules/@aws-sdk/types": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.953.0.tgz",
+ "integrity": "sha512-M9Iwg9kTyqTErI0vOTVVpcnTHWzS3VplQppy8MuL02EE+mJ0BIwpWfsaAPQW+/XnVpdNpWZTsHcNE29f1+hR8g==",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/s3-request-presigner/node_modules/@aws-sdk/util-arn-parser": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.953.0.tgz",
+ "integrity": "sha512-9hqdKkn4OvYzzaLryq2xnwcrPc8ziY34i9szUdgBfSqEC6pBxbY9/lLXmrgzfwMSL2Z7/v2go4Od0p5eukKLMQ==",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/s3-request-presigner/node_modules/@aws-sdk/xml-builder": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.953.0.tgz",
+ "integrity": "sha512-Zmrj21jQ2OeOJGr9spPiN00aQvXa/WUqRXcTVENhrMt+OFoSOfDFpYhUj9NQ09QmQ8KMWFoWuWW6iKurNqLvAA==",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "fast-xml-parser": "5.2.5",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/s3-request-presigner/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
"node_modules/@aws-sdk/signature-v4-multi-region": {
"version": "3.932.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.932.0.tgz",
@@ -927,7 +2164,38 @@
"node": ">=18.0.0"
}
},
- "node_modules/@aws-sdk/util-endpoints/node_modules/tslib": {
+ "node_modules/@aws-sdk/util-endpoints/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/@aws-sdk/util-format-url": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.953.0.tgz",
+ "integrity": "sha512-fs70vtTiBhp/T9ss52OuW2LGJqPoNBbd1+wxqh82CMdzkOvCzI3qa/cK8tR0jCFeIjGeiV74lAskImRxu/V4lg==",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/querystring-builder": "^4.2.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-format-url/node_modules/@aws-sdk/types": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.953.0.tgz",
+ "integrity": "sha512-M9Iwg9kTyqTErI0vOTVVpcnTHWzS3VplQppy8MuL02EE+mJ0BIwpWfsaAPQW+/XnVpdNpWZTsHcNE29f1+hR8g==",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-format-url/node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
@@ -1011,9 +2279,9 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@aws/lambda-invoke-store": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.0.tgz",
- "integrity": "sha512-D1jAmAZQYMoPiacfgNf7AWhg3DFN3Wq/vQv3WINt9znwjzHp2x+WzdJFxxj7xZL7V1U79As6G8f7PorMYWBKsQ==",
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.2.tgz",
+ "integrity": "sha512-C0NBLsIqzDIae8HFw9YIrIBsbc0xTiOtt7fAukGPnqQ/+zZNaq+4jhuccltK0QuWHBnNm/a6kLIRA6GFiM10eg==",
"engines": {
"node": ">=18.0.0"
}
@@ -2618,11 +3886,11 @@
}
},
"node_modules/@smithy/abort-controller": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.5.tgz",
- "integrity": "sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA==",
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.6.tgz",
+ "integrity": "sha512-P7JD4J+wxHMpGxqIg6SHno2tPkZbBUBLbPpR5/T1DEUvw/mEaINBMaPFZNM7lA+ToSCZ36j6nMHa+5kej+fhGg==",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.10.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -2634,16 +3902,49 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
+ "node_modules/@smithy/chunked-blob-reader": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.2.0.tgz",
+ "integrity": "sha512-WmU0TnhEAJLWvfSeMxBNe5xtbselEO8+4wG0NtZeL8oR21WgH1xiO37El+/Y+H/Ie4SCwBy3MxYWmOYaGgZueA==",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/chunked-blob-reader-native": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.2.1.tgz",
+ "integrity": "sha512-lX9Ay+6LisTfpLid2zZtIhSEjHMZoAR5hHCR4H7tBz/Zkfr5ea8RcQ7Tk4mi0P76p4cN+Btz16Ffno7YHpKXnQ==",
+ "dependencies": {
+ "@smithy/util-base64": "^4.3.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/chunked-blob-reader-native/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/@smithy/chunked-blob-reader/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
"node_modules/@smithy/config-resolver": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.3.tgz",
- "integrity": "sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw==",
+ "version": "4.4.4",
+ "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.4.tgz",
+ "integrity": "sha512-s3U5ChS21DwU54kMmZ0UJumoS5cg0+rGVZvN6f5Lp6EbAVi0ZyP+qDSHdewfmXKUgNK1j3z45JyzulkDukrjAA==",
"dependencies": {
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/types": "^4.10.0",
"@smithy/util-config-provider": "^4.2.0",
- "@smithy/util-endpoints": "^3.2.5",
- "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-endpoints": "^3.2.6",
+ "@smithy/util-middleware": "^4.2.6",
"tslib": "^2.6.2"
},
"engines": {
@@ -2656,17 +3957,17 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/core": {
- "version": "3.18.4",
- "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.18.4.tgz",
- "integrity": "sha512-o5tMqPZILBvvROfC8vC+dSVnWJl9a0u9ax1i1+Bq8515eYjUJqqk5XjjEsDLoeL5dSqGSh6WGdVx1eJ1E/Nwhw==",
+ "version": "3.19.0",
+ "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.19.0.tgz",
+ "integrity": "sha512-Y9oHXpBcXQgYHOcAEmxjkDilUbSTkgKjoHYed3WaYUH8jngq8lPWDBSpjHblJ9uOgBdy5mh3pzebrScDdYr29w==",
"dependencies": {
- "@smithy/middleware-serde": "^4.2.6",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/middleware-serde": "^4.2.7",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
"@smithy/util-base64": "^4.3.0",
"@smithy/util-body-length-browser": "^4.2.0",
- "@smithy/util-middleware": "^4.2.5",
- "@smithy/util-stream": "^4.5.6",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-stream": "^4.5.7",
"@smithy/util-utf8": "^4.2.0",
"@smithy/uuid": "^1.1.0",
"tslib": "^2.6.2"
@@ -2681,14 +3982,14 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/credential-provider-imds": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.5.tgz",
- "integrity": "sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ==",
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.6.tgz",
+ "integrity": "sha512-xBmawExyTzOjbhzkZwg+vVm/khg28kG+rj2sbGlULjFd1jI70sv/cbpaR0Ev4Yfd6CpDUDRMe64cTqR//wAOyA==",
"dependencies": {
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/property-provider": "^4.2.5",
- "@smithy/types": "^4.9.0",
- "@smithy/url-parser": "^4.2.5",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/types": "^4.10.0",
+ "@smithy/url-parser": "^4.2.6",
"tslib": "^2.6.2"
},
"engines": {
@@ -2700,14 +4001,104 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
+ "node_modules/@smithy/eventstream-codec": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.2.6.tgz",
+ "integrity": "sha512-OZfsI+YRG26XZik/jKMMg37acnBSbUiK/8nETW3uM3mLj+0tMmFXdHQw1e5WEd/IHN8BGOh3te91SNDe2o4RHg==",
+ "dependencies": {
+ "@aws-crypto/crc32": "5.2.0",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-hex-encoding": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-codec/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/@smithy/eventstream-serde-browser": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.6.tgz",
+ "integrity": "sha512-6OiaAaEbLB6dEkRbQyNzFSJv5HDvly3Mc6q/qcPd2uS/g3szR8wAIkh7UndAFKfMypNSTuZ6eCBmgCLR5LacTg==",
+ "dependencies": {
+ "@smithy/eventstream-serde-universal": "^4.2.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-browser/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/@smithy/eventstream-serde-config-resolver": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.6.tgz",
+ "integrity": "sha512-xP5YXbOVRVN8A4pDnSUkEUsL9fYFU6VNhxo8tgr13YnMbf3Pn4xVr+hSyLVjS1Frfi1Uk03ET5Bwml4+0CeYEw==",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-config-resolver/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/@smithy/eventstream-serde-node": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.6.tgz",
+ "integrity": "sha512-jhH7nJuaOpnTFcuZpWK9dqb6Ge2yGi1okTo0W6wkJrfwAm2vwmO74tF1v07JmrSyHBcKLQATEexclJw9K1Vj7w==",
+ "dependencies": {
+ "@smithy/eventstream-serde-universal": "^4.2.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-node/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/@smithy/eventstream-serde-universal": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.6.tgz",
+ "integrity": "sha512-olIfZ230B64TvPD6b0tPvrEp2eB0FkyL3KvDlqF4RVmIc/kn3orzXnV6DTQdOOW5UU+M5zKY3/BU47X420/oPw==",
+ "dependencies": {
+ "@smithy/eventstream-codec": "^4.2.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-universal/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
"node_modules/@smithy/fetch-http-handler": {
- "version": "5.3.6",
- "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.6.tgz",
- "integrity": "sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg==",
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.7.tgz",
+ "integrity": "sha512-fcVap4QwqmzQwQK9QU3keeEpCzTjnP9NJ171vI7GnD7nbkAIcP9biZhDUx88uRH9BabSsQDS0unUps88uZvFIQ==",
"dependencies": {
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/querystring-builder": "^4.2.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/querystring-builder": "^4.2.6",
+ "@smithy/types": "^4.10.0",
"@smithy/util-base64": "^4.3.0",
"tslib": "^2.6.2"
},
@@ -2720,12 +4111,31 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
+ "node_modules/@smithy/hash-blob-browser": {
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.2.7.tgz",
+ "integrity": "sha512-CIbCTGGX5CI7tfewBPSYD9ycp2Vb2GW5xnXD1n7GcO9mu37EN7A6DvCHM9MX7pOeS1adMn5D+1yRwI3eABVbcA==",
+ "dependencies": {
+ "@smithy/chunked-blob-reader": "^5.2.0",
+ "@smithy/chunked-blob-reader-native": "^4.2.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/hash-blob-browser/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
"node_modules/@smithy/hash-node": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.5.tgz",
- "integrity": "sha512-DpYX914YOfA3UDT9CN1BM787PcHfWRBB43fFGCYrZFUH0Jv+5t8yYl+Pd5PW4+QzoGEDvn5d5QIO4j2HyYZQSA==",
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.6.tgz",
+ "integrity": "sha512-k3Dy9VNR37wfMh2/1RHkFf/e0rMyN0pjY0FdyY6ItJRjENYyVPRMwad6ZR1S9HFm6tTuIOd9pqKBmtJ4VHxvxg==",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.10.0",
"@smithy/util-buffer-from": "^4.2.0",
"@smithy/util-utf8": "^4.2.0",
"tslib": "^2.6.2"
@@ -2739,12 +4149,30 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
+ "node_modules/@smithy/hash-stream-node": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.2.6.tgz",
+ "integrity": "sha512-+3T8LkH39YIhYHsv/Ec8lF+92nykZpU+XMBvAyXF/uLcTp86pxa5oSJk1vzaRY9N++qgDLYjzJ6OVbtAgDGwfw==",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/hash-stream-node/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
"node_modules/@smithy/invalid-dependency": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.5.tgz",
- "integrity": "sha512-2L2erASEro1WC5nV+plwIMxrTXpvpfzl4e+Nre6vBVRR2HKeGGcvpJyyL3/PpiSg+cJG2KpTmZmq934Olb6e5A==",
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.6.tgz",
+ "integrity": "sha512-E4t/V/q2T46RY21fpfznd1iSLTvCXKNKo4zJ1QuEFN4SE9gKfu2vb6bgq35LpufkQ+SETWIC7ZAf2GGvTlBaMQ==",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.10.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -2772,13 +4200,31 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
+ "node_modules/@smithy/md5-js": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.2.6.tgz",
+ "integrity": "sha512-ZXeh8UmH31JdcNsrQ1o9v1IVuva9JFwxIc6zTMxWX7wcmWvVR7Ai9aUEw5LraNKqdkAsb06clpM2sRH4Iy55Sg==",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/md5-js/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
"node_modules/@smithy/middleware-content-length": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.5.tgz",
- "integrity": "sha512-Y/RabVa5vbl5FuHYV2vUCwvh/dqzrEY/K2yWPSqvhFUwIY0atLqO4TienjBXakoy4zrKAMCZwg+YEqmH7jaN7A==",
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.6.tgz",
+ "integrity": "sha512-0cjqjyfj+Gls30ntq45SsBtqF3dfJQCeqQPyGz58Pk8OgrAr5YiB7ZvDzjCA94p4r6DCI4qLm7FKobqBjf515w==",
"dependencies": {
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -2791,17 +4237,17 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/middleware-endpoint": {
- "version": "4.3.11",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.3.11.tgz",
- "integrity": "sha512-eJXq9VJzEer1W7EQh3HY2PDJdEcEUnv6sKuNt4eVjyeNWcQFS4KmnY+CKkYOIR6tSqarn6bjjCqg1UB+8UJiPQ==",
- "dependencies": {
- "@smithy/core": "^3.18.4",
- "@smithy/middleware-serde": "^4.2.6",
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/shared-ini-file-loader": "^4.4.0",
- "@smithy/types": "^4.9.0",
- "@smithy/url-parser": "^4.2.5",
- "@smithy/util-middleware": "^4.2.5",
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.0.tgz",
+ "integrity": "sha512-M6qWfUNny6NFNy8amrCGIb9TfOMUkHVtg9bHtEFGRgfH7A7AtPpn/fcrToGPjVDK1ECuMVvqGQOXcZxmu9K+7A==",
+ "dependencies": {
+ "@smithy/core": "^3.19.0",
+ "@smithy/middleware-serde": "^4.2.7",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/shared-ini-file-loader": "^4.4.1",
+ "@smithy/types": "^4.10.0",
+ "@smithy/url-parser": "^4.2.6",
+ "@smithy/util-middleware": "^4.2.6",
"tslib": "^2.6.2"
},
"engines": {
@@ -2814,17 +4260,17 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/middleware-retry": {
- "version": "4.4.11",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.11.tgz",
- "integrity": "sha512-EL5OQHvFOKneJVRgzRW4lU7yidSwp/vRJOe542bHgExN3KNThr1rlg0iE4k4SnA+ohC+qlUxoK+smKeAYPzfAQ==",
- "dependencies": {
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/service-error-classification": "^4.2.5",
- "@smithy/smithy-client": "^4.9.7",
- "@smithy/types": "^4.9.0",
- "@smithy/util-middleware": "^4.2.5",
- "@smithy/util-retry": "^4.2.5",
+ "version": "4.4.16",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.16.tgz",
+ "integrity": "sha512-XPpNhNRzm3vhYm7YCsyw3AtmWggJbg1wNGAoqb7NBYr5XA5isMRv14jgbYyUV6IvbTBFZQdf2QpeW43LrRdStQ==",
+ "dependencies": {
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/service-error-classification": "^4.2.6",
+ "@smithy/smithy-client": "^4.10.1",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-retry": "^4.2.6",
"@smithy/uuid": "^1.1.0",
"tslib": "^2.6.2"
},
@@ -2838,12 +4284,12 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/middleware-serde": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.6.tgz",
- "integrity": "sha512-VkLoE/z7e2g8pirwisLz8XJWedUSY8my/qrp81VmAdyrhi94T+riBfwP+AOEEFR9rFTSonC/5D2eWNmFabHyGQ==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.7.tgz",
+ "integrity": "sha512-PFMVHVPgtFECeu4iZ+4SX6VOQT0+dIpm4jSPLLL6JLSkp9RohGqKBKD0cbiXdeIFS08Forp0UHI6kc0gIHenSA==",
"dependencies": {
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -2856,11 +4302,11 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/middleware-stack": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.5.tgz",
- "integrity": "sha512-bYrutc+neOyWxtZdbB2USbQttZN0mXaOyYLIsaTbJhFsfpXyGWUxJpEuO1rJ8IIJm2qH4+xJT0mxUSsEDTYwdQ==",
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.6.tgz",
+ "integrity": "sha512-JSbALU3G+JS4kyBZPqnJ3hxIYwOVRV7r9GNQMS6j5VsQDo5+Es5nddLfr9TQlxZLNHPvKSh+XSB0OuWGfSWFcA==",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.10.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -2873,13 +4319,13 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/node-config-provider": {
- "version": "4.3.5",
- "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.5.tgz",
- "integrity": "sha512-UTurh1C4qkVCtqggI36DGbLB2Kv8UlcFdMXDcWMbqVY2uRg0XmT9Pb4Vj6oSQ34eizO1fvR0RnFV4Axw4IrrAg==",
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.6.tgz",
+ "integrity": "sha512-fYEyL59Qe82Ha1p97YQTMEQPJYmBS+ux76foqluaTVWoG9Px5J53w6NvXZNE3wP7lIicLDF7Vj1Em18XTX7fsA==",
"dependencies": {
- "@smithy/property-provider": "^4.2.5",
- "@smithy/shared-ini-file-loader": "^4.4.0",
- "@smithy/types": "^4.9.0",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/shared-ini-file-loader": "^4.4.1",
+ "@smithy/types": "^4.10.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -2892,14 +4338,14 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/node-http-handler": {
- "version": "4.4.5",
- "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.5.tgz",
- "integrity": "sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw==",
- "dependencies": {
- "@smithy/abort-controller": "^4.2.5",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/querystring-builder": "^4.2.5",
- "@smithy/types": "^4.9.0",
+ "version": "4.4.6",
+ "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.6.tgz",
+ "integrity": "sha512-Gsb9jf4ido5BhPfani4ggyrKDd3ZK+vTFWmUaZeFg5G3E5nhFmqiTzAIbHqmPs1sARuJawDiGMGR/nY+Gw6+aQ==",
+ "dependencies": {
+ "@smithy/abort-controller": "^4.2.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/querystring-builder": "^4.2.6",
+ "@smithy/types": "^4.10.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -2912,11 +4358,11 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/property-provider": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.5.tgz",
- "integrity": "sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg==",
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.6.tgz",
+ "integrity": "sha512-a/tGSLPtaia2krbRdwR4xbZKO8lU67DjMk/jfY4QKt4PRlKML+2tL/gmAuhNdFDioO6wOq0sXkfnddNFH9mNUA==",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.10.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -2929,11 +4375,11 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/protocol-http": {
- "version": "5.3.5",
- "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.5.tgz",
- "integrity": "sha512-RlaL+sA0LNMp03bf7XPbFmT5gN+w3besXSWMkA8rcmxLSVfiEXElQi4O2IWwPfxzcHkxqrwBFMbngB8yx/RvaQ==",
+ "version": "5.3.6",
+ "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.6.tgz",
+ "integrity": "sha512-qLRZzP2+PqhE3OSwvY2jpBbP0WKTZ9opTsn+6IWYI0SKVpbG+imcfNxXPq9fj5XeaUTr7odpsNpK6dmoiM1gJQ==",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.10.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -2946,11 +4392,11 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/querystring-builder": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.5.tgz",
- "integrity": "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg==",
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.6.tgz",
+ "integrity": "sha512-MeM9fTAiD3HvoInK/aA8mgJaKQDvm8N0dKy6EiFaCfgpovQr4CaOkJC28XqlSRABM+sHdSQXbC8NZ0DShBMHqg==",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.10.0",
"@smithy/util-uri-escape": "^4.2.0",
"tslib": "^2.6.2"
},
@@ -2964,11 +4410,11 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/querystring-parser": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.5.tgz",
- "integrity": "sha512-031WCTdPYgiQRYNPXznHXof2YM0GwL6SeaSyTH/P72M1Vz73TvCNH2Nq8Iu2IEPq9QP2yx0/nrw5YmSeAi/AjQ==",
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.6.tgz",
+ "integrity": "sha512-YmWxl32SQRw/kIRccSOxzS/Ib8/b5/f9ex0r5PR40jRJg8X1wgM3KrR2In+8zvOGVhRSXgvyQpw9yOSlmfmSnA==",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.10.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -2981,22 +4427,22 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/service-error-classification": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.5.tgz",
- "integrity": "sha512-8fEvK+WPE3wUAcDvqDQG1Vk3ANLR8Px979te96m84CbKAjBVf25rPYSzb4xU4hlTyho7VhOGnh5i62D/JVF0JQ==",
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.6.tgz",
+ "integrity": "sha512-Q73XBrzJlGTut2nf5RglSntHKgAG0+KiTJdO5QQblLfr4TdliGwIAha1iZIjwisc3rA5ulzqwwsYC6xrclxVQg==",
"dependencies": {
- "@smithy/types": "^4.9.0"
+ "@smithy/types": "^4.10.0"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@smithy/shared-ini-file-loader": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.0.tgz",
- "integrity": "sha512-5WmZ5+kJgJDjwXXIzr1vDTG+RhF9wzSODQBfkrQ2VVkYALKGvZX1lgVSxEkgicSAFnFhPj5rudJV0zoinqS0bA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.1.tgz",
+ "integrity": "sha512-tph+oQYPbpN6NamF030hx1gb5YN2Plog+GLaRHpoEDwp8+ZPG26rIJvStG9hkWzN2HBn3HcWg0sHeB0tmkYzqA==",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.10.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3009,15 +4455,15 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/signature-v4": {
- "version": "5.3.5",
- "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.5.tgz",
- "integrity": "sha512-xSUfMu1FT7ccfSXkoLl/QRQBi2rOvi3tiBZU2Tdy3I6cgvZ6SEi9QNey+lqps/sJRnogIS+lq+B1gxxbra2a/w==",
+ "version": "5.3.6",
+ "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.6.tgz",
+ "integrity": "sha512-P1TXDHuQMadTMTOBv4oElZMURU4uyEhxhHfn+qOc2iofW9Rd4sZtBGx58Lzk112rIGVEYZT8eUMK4NftpewpRA==",
"dependencies": {
"@smithy/is-array-buffer": "^4.2.0",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
"@smithy/util-hex-encoding": "^4.2.0",
- "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-middleware": "^4.2.6",
"@smithy/util-uri-escape": "^4.2.0",
"@smithy/util-utf8": "^4.2.0",
"tslib": "^2.6.2"
@@ -3032,16 +4478,16 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/smithy-client": {
- "version": "4.9.7",
- "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.9.7.tgz",
- "integrity": "sha512-pskaE4kg0P9xNQWihfqlTMyxyFR3CH6Sr6keHYghgyqqDXzjl2QJg5lAzuVe/LzZiOzcbcVtxKYi1/fZPt/3DA==",
- "dependencies": {
- "@smithy/core": "^3.18.4",
- "@smithy/middleware-endpoint": "^4.3.11",
- "@smithy/middleware-stack": "^4.2.5",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/types": "^4.9.0",
- "@smithy/util-stream": "^4.5.6",
+ "version": "4.10.1",
+ "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.10.1.tgz",
+ "integrity": "sha512-1ovWdxzYprhq+mWqiGZlt3kF69LJthuQcfY9BIyHx9MywTFKzFapluku1QXoaBB43GCsLDxNqS+1v30ure69AA==",
+ "dependencies": {
+ "@smithy/core": "^3.19.0",
+ "@smithy/middleware-endpoint": "^4.4.0",
+ "@smithy/middleware-stack": "^4.2.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-stream": "^4.5.7",
"tslib": "^2.6.2"
},
"engines": {
@@ -3054,9 +4500,9 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/types": {
- "version": "4.9.0",
- "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.9.0.tgz",
- "integrity": "sha512-MvUbdnXDTwykR8cB1WZvNNwqoWVaTRA0RLlLmf/cIFNMM2cKWz01X4Ly6SMC4Kks30r8tT3Cty0jmeWfiuyHTA==",
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.10.0.tgz",
+ "integrity": "sha512-K9mY7V/f3Ul+/Gz4LJANZ3vJ/yiBIwCyxe0sPT4vNJK63Srvd+Yk1IzP0t+nE7XFSpIGtzR71yljtnqpUTYFlQ==",
"dependencies": {
"tslib": "^2.6.2"
},
@@ -3070,12 +4516,12 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/url-parser": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.5.tgz",
- "integrity": "sha512-VaxMGsilqFnK1CeBX+LXnSuaMx4sTL/6znSZh2829txWieazdVxr54HmiyTsIbpOTLcf5nYpq9lpzmwRdxj6rQ==",
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.6.tgz",
+ "integrity": "sha512-tVoyzJ2vXp4R3/aeV4EQjBDmCuWxRa8eo3KybL7Xv4wEM16nObYh7H1sNfcuLWHAAAzb0RVyxUz1S3sGj4X+Tg==",
"dependencies": {
- "@smithy/querystring-parser": "^4.2.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/querystring-parser": "^4.2.6",
+ "@smithy/types": "^4.10.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3171,13 +4617,13 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/util-defaults-mode-browser": {
- "version": "4.3.10",
- "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.10.tgz",
- "integrity": "sha512-3iA3JVO1VLrP21FsZZpMCeF93aqP3uIOMvymAT3qHIJz2YlgDeRvNUspFwCNqd/j3qqILQJGtsVQnJZICh/9YA==",
+ "version": "4.3.15",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.15.tgz",
+ "integrity": "sha512-LiZQVAg/oO8kueX4c+oMls5njaD2cRLXRfcjlTYjhIqmwHnCwkQO5B3dMQH0c5PACILxGAQf6Mxsq7CjlDc76A==",
"dependencies": {
- "@smithy/property-provider": "^4.2.5",
- "@smithy/smithy-client": "^4.9.7",
- "@smithy/types": "^4.9.0",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/smithy-client": "^4.10.1",
+ "@smithy/types": "^4.10.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3190,16 +4636,16 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/util-defaults-mode-node": {
- "version": "4.2.13",
- "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.13.tgz",
- "integrity": "sha512-PTc6IpnpSGASuzZAgyUtaVfOFpU0jBD2mcGwrgDuHf7PlFgt5TIPxCYBDbFQs06jxgeV3kd/d/sok1pzV0nJRg==",
- "dependencies": {
- "@smithy/config-resolver": "^4.4.3",
- "@smithy/credential-provider-imds": "^4.2.5",
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/property-provider": "^4.2.5",
- "@smithy/smithy-client": "^4.9.7",
- "@smithy/types": "^4.9.0",
+ "version": "4.2.18",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.18.tgz",
+ "integrity": "sha512-Kw2J+KzYm9C9Z9nY6+W0tEnoZOofstVCMTshli9jhQbQCy64rueGfKzPfuFBnVUqZD9JobxTh2DzHmPkp/Va/Q==",
+ "dependencies": {
+ "@smithy/config-resolver": "^4.4.4",
+ "@smithy/credential-provider-imds": "^4.2.6",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/smithy-client": "^4.10.1",
+ "@smithy/types": "^4.10.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3212,12 +4658,12 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/util-endpoints": {
- "version": "3.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.5.tgz",
- "integrity": "sha512-3O63AAWu2cSNQZp+ayl9I3NapW1p1rR5mlVHcF6hAB1dPZUQFfRPYtplWX/3xrzWthPGj5FqB12taJJCfH6s8A==",
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.6.tgz",
+ "integrity": "sha512-v60VNM2+mPvgHCBXEfMCYrQ0RepP6u6xvbAkMenfe4Mi872CqNkJzgcnQL837e8NdeDxBgrWQRTluKq5Lqdhfg==",
"dependencies": {
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/types": "^4.10.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3246,11 +4692,11 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/util-middleware": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.5.tgz",
- "integrity": "sha512-6Y3+rvBF7+PZOc40ybeZMcGln6xJGVeY60E7jy9Mv5iKpMJpHgRE6dKy9ScsVxvfAYuEX4Q9a65DQX90KaQ3bA==",
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.6.tgz",
+ "integrity": "sha512-qrvXUkxBSAFomM3/OEMuDVwjh4wtqK8D2uDZPShzIqOylPst6gor2Cdp6+XrH4dyksAWq/bE2aSDYBTTnj0Rxg==",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.10.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3263,12 +4709,12 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/util-retry": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.5.tgz",
- "integrity": "sha512-GBj3+EZBbN4NAqJ/7pAhsXdfzdlznOh8PydUijy6FpNIMnHPSMO2/rP4HKu+UFeikJxShERk528oy7GT79YiJg==",
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.6.tgz",
+ "integrity": "sha512-x7CeDQLPQ9cb6xN7fRJEjlP9NyGW/YeXWc4j/RUhg4I+H60F0PEeRc2c/z3rm9zmsdiMFzpV/rT+4UHW6KM1SA==",
"dependencies": {
- "@smithy/service-error-classification": "^4.2.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/service-error-classification": "^4.2.6",
+ "@smithy/types": "^4.10.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3281,13 +4727,13 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/util-stream": {
- "version": "4.5.6",
- "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.6.tgz",
- "integrity": "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ==",
+ "version": "4.5.7",
+ "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.7.tgz",
+ "integrity": "sha512-Uuy4S5Aj4oF6k1z+i2OtIBJUns4mlg29Ph4S+CqjR+f4XXpSFVgTCYLzMszHJTicYDBxKFtwq2/QSEDSS5l02A==",
"dependencies": {
- "@smithy/fetch-http-handler": "^5.3.6",
- "@smithy/node-http-handler": "^4.4.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/fetch-http-handler": "^5.3.7",
+ "@smithy/node-http-handler": "^4.4.6",
+ "@smithy/types": "^4.10.0",
"@smithy/util-base64": "^4.3.0",
"@smithy/util-buffer-from": "^4.2.0",
"@smithy/util-hex-encoding": "^4.2.0",
@@ -3337,12 +4783,12 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/@smithy/util-waiter": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.5.tgz",
- "integrity": "sha512-Dbun99A3InifQdIrsXZ+QLcC0PGBPAdrl4cj1mTgJvyc9N2zf7QSxg8TBkzsCmGJdE3TLbO9ycwpY0EkWahQ/g==",
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.6.tgz",
+ "integrity": "sha512-xU9HwUSik9UUCJmm530yvBy0AwlQFICveKmqvaaTukKkXEAhyiBdHtSrhPrH3rH+uz0ykyaE3LdgsX86C6mDCQ==",
"dependencies": {
- "@smithy/abort-controller": "^4.2.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/abort-controller": "^4.2.6",
+ "@smithy/types": "^4.10.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3582,6 +5028,15 @@
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
"dev": true
},
+ "node_modules/@types/multer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.0.0.tgz",
+ "integrity": "sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==",
+ "dev": true,
+ "dependencies": {
+ "@types/express": "*"
+ }
+ },
"node_modules/@types/node": {
"version": "16.18.126",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz",
@@ -5692,7 +7147,6 @@
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
- "dev": true,
"engines": {
"node": ">=0.8.x"
}
@@ -9275,6 +10729,28 @@
"node": ">= 0.8"
}
},
+ "node_modules/stream-browserify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz",
+ "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==",
+ "dependencies": {
+ "inherits": "~2.0.4",
+ "readable-stream": "^3.5.0"
+ }
+ },
+ "node_modules/stream-browserify/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/streamsearch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
diff --git a/package.json b/package.json
index 783e82b..96a81e6 100644
--- a/package.json
+++ b/package.json
@@ -26,11 +26,14 @@
"db:migrate": "npm run typeorm migration:run -- -d src/database/datasource.ts",
"db:revert": "npm run typeorm migration:revert -- -d src/database/datasource.ts",
"db:drop": "npm run typeorm schema:drop -- -d src/database/datasource.ts",
- "db:migrate:prod": "node ./node_modules/typeorm/cli migration:run -- -d ./dist/database/datasource.js"
+ "db:migrate:prod": "node ./node_modules/typeorm/cli migration:run -d ./dist/database/datasource.js"
},
"dependencies": {
+ "@aws-sdk/client-s3": "^3.954.0",
"@aws-sdk/client-ses": "^3.933.0",
"@aws-sdk/client-sesv2": "^3.933.0",
+ "@aws-sdk/lib-storage": "^3.954.0",
+ "@aws-sdk/s3-request-presigner": "^3.954.0",
"@nestjs/common": "^9.0.0",
"@nestjs/config": "^4.0.2",
"@nestjs/core": "^9.0.0",
@@ -53,6 +56,7 @@
"@nestjs/testing": "^9.0.0",
"@types/express": "^4.17.13",
"@types/jest": "28.1.8",
+ "@types/multer": "^2.0.0",
"@types/node": "^16.0.0",
"@types/supertest": "^2.0.11",
"@types/uuid": "^11.0.0",
diff --git a/schemas/get-birth-certificate.json b/schemas/get-birth-certificate.json
index 9ab9abe..b27c524 100644
--- a/schemas/get-birth-certificate.json
+++ b/schemas/get-birth-certificate.json
@@ -1,265 +1,518 @@
{
- "id": "get-birth-certificate",
- "name": "Get Birth Certificate",
- "description": "Apply for a copy of your birth certificate or someone else's birth certificate",
- "fields": [
- {
- "name": "applicant",
- "type": "object",
- "required": true,
- "fields": [
- {
- "name": "title",
- "type": "string",
- "label": "Title",
- "required": true,
- "validations": {
- "regex": "^(mr|ms|mrs)$",
- "message": "Must select a valid title"
- }
- },
- {
- "name": "firstName",
- "type": "string",
- "label": "First name",
- "required": true,
- "validations": {
- "min": 1,
- "max": 100,
- "message": "First name is required"
- }
- },
- {
- "name": "middleName",
- "type": "string",
- "label": "Middle name",
- "required": false,
- "validations": {
- "max": 100
- }
- },
- {
- "name": "lastName",
- "type": "string",
- "label": "Last name",
- "required": true,
- "validations": {
- "min": 1,
- "max": 100,
- "message": "Last name is required"
- }
- },
- {
- "name": "addressLine1",
- "type": "string",
- "label": "Address Line 1",
- "required": true,
- "validations": {
- "min": 5,
- "max": 200,
- "message": "Address must be at least 5 characters"
- }
- },
- {
- "name": "addressLine2",
- "type": "string",
- "label": "Address Line 2",
- "required": false,
- "validations": {
- "max": 200
- }
- },
- {
- "name": "parish",
- "type": "string",
- "label": "Parish",
- "required": true,
- "validations": {
- "regex": "^(christ-church|st-andrew|st-george|st-james|st-john|st-joseph|st-lucy|st-michael|st-peter|st-philip|st-thomas)$",
- "message": "Must select a valid parish"
- }
- },
- {
- "name": "postalCode",
- "type": "string",
- "label": "Postal Code",
- "required": false,
- "validations": {
- "regex": "^BB\\d{5}$",
- "message": "Enter a valid postal code (e.g., BB17004)"
- }
- },
- {
- "name": "idNumber",
- "type": "string",
- "label": "National Identification (ID) Number",
- "required": false,
- "validations": {
- "min": 2,
- "message": "ID Number must be at least 2 characters"
- }
- },
- {
- "name": "passportNumber",
- "type": "string",
- "label": "Passport Number",
- "required": false,
- "validations": {
- "message": "Passport number must be at least 6 characters"
- }
- }
- ]
- },
- {
- "name": "applyingForYourself",
- "type": "string",
- "label": "Are you applying for your own birth certificate?",
- "required": true,
- "validations": {
- "regex": "^(yes|no)$",
- "message": "Must select an option"
- }
- },
- {
- "name": "birthDetails",
- "type": "object",
- "required": true,
- "fields": [
- {
- "name": "dateOfBirth",
- "type": "date",
- "label": "Date of birth",
- "required": true,
- "validations": {
- "regex": "^\\d{4}-\\d{2}-\\d{2}$",
- "message": "Date of birth is required and must be in YYYY-MM-DD format"
- }
- },
- {
- "name": "placeOfBirth",
- "type": "string",
- "label": "Place of birth",
- "required": true,
- "validations": {
- "min": 2,
- "max": 200,
- "message": "Place of birth must be at least 2 characters"
- }
- },
- {
- "name": "placeOfBaptism",
- "type": "string",
- "label": "Place of baptism",
- "required": true,
- "validations": {
- "min": 2,
- "max": 200,
- "message": "Place of baptism must be at least 2 characters"
- }
- }
- ]
- },
- {
- "name": "parents",
- "type": "object",
- "required": true,
- "fields": [
- {
- "name": "father",
- "type": "object",
- "required": true,
- "fields": [
- {
- "name": "firstName",
- "type": "string",
- "label": "Father's first name",
- "required": true,
- "validations": {
- "min": 1,
- "max": 100,
- "message": "First name is required"
- }
- },
- {
- "name": "lastName",
- "type": "string",
- "label": "Father's last name",
- "required": true,
- "validations": {
- "min": 1,
- "max": 100,
- "message": "Last name is required"
- }
- }
- ]
- },
- {
- "name": "mother",
- "type": "object",
- "required": true,
- "fields": [
- {
- "name": "firstName",
- "type": "string",
- "label": "Mother's first name",
- "required": true,
- "validations": {
- "min": 1,
- "max": 100,
- "message": "First name is required"
- }
- },
- {
- "name": "lastName",
- "type": "string",
- "label": "Mother's last name",
- "required": true,
- "validations": {
- "min": 1,
- "max": 100,
- "message": "Last name is required"
- }
- }
- ]
- }
- ]
- },
- {
- "name": "order",
- "type": "object",
- "required": true,
- "fields": [
- {
- "name": "numberOfCopies",
- "type": "number",
- "label": "Number of copies",
- "required": true,
- "validations": {
- "message": "You must order at least 1 copy and maximum 10 copies"
- }
- }
- ]
- }
- ],
- "processors": [
- {
- "type": "payment",
- "config": {
- "provider": "ezpay",
- "paymentCode": "{{db:get-birth-certificate:payment_code}}",
- "amount": 25.0,
- "description": "Processing Fee",
- "required": true,
- "timing": "after_validation"
- }
- },
- {
- "type": "email",
- "config": {
- "to": "{{db:get-birth-certificate:admin_email}}",
- "subject": "New Birth Certificate Application - {{formData.applicant.firstName}} {{formData.applicant.lastName}}",
- "template": "birth-certificate"
- }
- }
- ]
+ "id": "get-birth-certificate",
+ "name": "Get Birth Certificate",
+ "description": "Apply for a copy of your birth certificate or someone else's birth certificate",
+ "fields": [
+ {
+ "name": "applicant",
+ "type": "object",
+ "required": true,
+ "fields": [
+ {
+ "name": "title",
+ "type": "string",
+ "label": "Title",
+ "required": true,
+ "validations": {
+ "regex": "^(mr|ms|mrs)$",
+ "message": "Must select a valid title"
+ }
+ },
+ {
+ "name": "firstName",
+ "type": "string",
+ "label": "First name",
+ "required": true,
+ "validations": {
+ "min": 1,
+ "max": 100,
+ "message": "First name is required"
+ }
+ },
+ {
+ "name": "middleName",
+ "type": "string",
+ "label": "Middle name",
+ "required": false,
+ "validations": {
+ "max": 100
+ }
+ },
+ {
+ "name": "lastName",
+ "type": "string",
+ "label": "Last name",
+ "required": true,
+ "validations": {
+ "min": 1,
+ "max": 100,
+ "message": "Last name is required"
+ }
+ },
+ {
+ "name": "addressLine1",
+ "type": "string",
+ "label": "Address Line 1",
+ "required": true,
+ "validations": {
+ "min": 5,
+ "max": 200,
+ "message": "Address must be at least 5 characters"
+ }
+ },
+ {
+ "name": "addressLine2",
+ "type": "string",
+ "label": "Address Line 2",
+ "required": false,
+ "validations": {
+ "max": 200
+ }
+ },
+ {
+ "name": "parish",
+ "type": "string",
+ "label": "Parish",
+ "required": true,
+ "validations": {
+ "regex": "^(christ-church|st-andrew|st-george|st-james|st-john|st-joseph|st-lucy|st-michael|st-peter|st-philip|st-thomas)$",
+ "message": "Must select a valid parish"
+ }
+ },
+ {
+ "name": "postalCode",
+ "type": "string",
+ "label": "Postal Code",
+ "required": false,
+ "validations": {
+ "regex": "^BB\\d{5}$",
+ "message": "Enter a valid postal code (e.g., BB17004)"
+ }
+ },
+ {
+ "name": "idNumber",
+ "type": "string",
+ "label": "National Identification (ID) Number",
+ "required": false,
+ "validations": {
+ "min": 2,
+ "message": "ID Number must be at least 2 characters"
+ }
+ },
+ {
+ "name": "passportNumber",
+ "type": "string",
+ "label": "Passport Number",
+ "required": false,
+ "validations": {
+ "message": "Passport number must be at least 6 characters"
+ }
+ }
+ ]
+ },
+ {
+ "name": "applyingForYourself",
+ "type": "string",
+ "label": "Are you applying for your own birth certificate?",
+ "required": true,
+ "validations": {
+ "regex": "^(yes|no)$",
+ "message": "Must select an option"
+ }
+ },
+ {
+ "name": "relationshipToPerson",
+ "type": "string",
+ "label": "What is your relationship to the person?",
+ "required": false,
+ "validations": {
+ "message": ""
+ }
+ },
+ {
+ "name": "relationshipOtherDescription",
+ "type": "string",
+ "label": "Please describe your relationship",
+ "required": false,
+ "validations": {
+ "message": ""
+ }
+ },
+ {
+ "name": "reasonForOrderingCertificate",
+ "type": "string",
+ "label": "Tell us why you're ordering a birth certificate",
+ "required": false,
+ "validations": {
+ "message": ""
+ }
+ },
+ {
+ "name": "personDeceased",
+ "type": "string",
+ "label": "Is the person deceased?",
+ "required": false,
+ "validations": {
+ "message": ""
+ }
+ },
+ {
+ "name": "dateOfDeath",
+ "type": "string",
+ "label": "Date of death",
+ "required": false,
+ "validations": {
+ "message": ""
+ }
+ },
+ {
+ "name": "person",
+ "type": "object",
+ "required": false,
+ "fields": [
+ {
+ "name": "firstName",
+ "type": "string",
+ "label": "First name",
+ "required": false,
+ "validations": {
+ "min": 1,
+ "max": 100,
+ "message": "First name is required"
+ }
+ },
+ {
+ "name": "middleName",
+ "type": "string",
+ "label": "Middle name",
+ "required": false,
+ "validations": {
+ "max": 100
+ }
+ },
+ {
+ "name": "lastName",
+ "type": "string",
+ "label": "Last name",
+ "required": false,
+ "validations": {
+ "min": 1,
+ "max": 100,
+ "message": "Last name is required"
+ }
+ },
+ {
+ "name": "addressLine1",
+ "type": "string",
+ "label": "Address Line 1",
+ "required": false,
+ "validations": {
+ "min": 5,
+ "max": 200,
+ "message": "Address must be at least 5 characters"
+ }
+ },
+ {
+ "name": "addressLine2",
+ "type": "string",
+ "label": "Address Line 2",
+ "required": false,
+ "validations": {
+ "max": 200
+ }
+ },
+ {
+ "name": "parish",
+ "type": "string",
+ "label": "Parish",
+ "required": false,
+ "validations": {
+ "regex": "^(christ-church|st-andrew|st-george|st-james|st-john|st-joseph|st-lucy|st-michael|st-peter|st-philip|st-thomas)$",
+ "message": "Must select a valid parish"
+ }
+ },
+ {
+ "name": "postalCode",
+ "type": "string",
+ "label": "Postal Code",
+ "required": false,
+ "validations": {
+ "regex": "^BB\\d{5}$",
+ "message": "Enter a valid postal code (e.g., BB17004)"
+ }
+ },
+ {
+ "name": "idNumber",
+ "type": "string",
+ "label": "National Identification (ID) Number",
+ "required": false,
+ "validations": {
+ "min": 2,
+ "message": "ID Number must be at least 2 characters"
+ }
+ },
+ {
+ "name": "passportNumber",
+ "type": "string",
+ "label": "Passport Number",
+ "required": false,
+ "validations": {
+ "message": "Passport number must be at least 6 characters"
+ }
+ }
+ ]
+ },
+ {
+ "name": "birthDetails",
+ "type": "object",
+ "required": false,
+ "fields": [
+ {
+ "name": "dateOfBirth",
+ "type": "date",
+ "label": "Date of birth",
+ "required": false,
+ "validations": {
+ "regex": "^\\d{4}-\\d{2}-\\d{2}$",
+ "message": "Date of birth is required and must be in YYYY-MM-DD format"
+ }
+ },
+ {
+ "name": "placeOfBirth",
+ "type": "string",
+ "label": "Place of birth",
+ "required": false,
+ "validations": {
+ "min": 2,
+ "max": 200,
+ "message": "Place of birth must be at least 2 characters"
+ }
+ },
+ {
+ "name": "placeOfBaptism",
+ "type": "string",
+ "label": "Place of baptism",
+ "required": false,
+ "validations": {
+ "min": 2,
+ "max": 200,
+ "message": "Place of baptism must be at least 2 characters"
+ }
+ }
+ ]
+ },
+ {
+ "name": "parents",
+ "type": "object",
+ "required": false,
+ "fields": [
+ {
+ "name": "father",
+ "type": "object",
+ "required": false,
+ "fields": [
+ {
+ "name": "firstName",
+ "type": "string",
+ "label": "Father's first name",
+ "required": false,
+ "validations": {
+ "min": 1,
+ "max": 100,
+ "message": "First name is required"
+ }
+ },
+ {
+ "name": "middleName",
+ "type": "string",
+ "label": "Father's middle name",
+ "required": false,
+ "validations": {
+ "max": 100,
+ "message": "Middle name is required"
+ }
+ },
+ {
+ "name": "lastName",
+ "type": "string",
+ "label": "Father's last name",
+ "required": false,
+ "validations": {
+ "min": 1,
+ "max": 100,
+ "message": "Last name is required"
+ }
+ }
+ ]
+ },
+ {
+ "name": "mother",
+ "type": "object",
+ "required": false,
+ "fields": [
+ {
+ "name": "firstName",
+ "type": "string",
+ "label": "Mother's first name",
+ "required": false,
+ "validations": {
+ "min": 1,
+ "max": 100,
+ "message": "First name is required"
+ }
+ },
+ {
+ "name": "middleName",
+ "type": "string",
+ "label": "Mother's middle name",
+ "required": false,
+ "validations": {
+ "max": 100,
+ "message": "Middle name is required"
+ }
+ },
+ {
+ "name": "lastName",
+ "type": "string",
+ "label": "Mother's last name",
+ "required": false,
+ "validations": {
+ "min": 1,
+ "max": 100,
+ "message": "Last name is required"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "parentsOther",
+ "type": "object",
+ "required": false,
+ "fields": [
+ {
+ "name": "father",
+ "type": "object",
+ "required": false,
+ "fields": [
+ {
+ "name": "firstName",
+ "type": "string",
+ "label": "Father's first name",
+ "required": false,
+ "validations": {
+ "min": 1,
+ "max": 100,
+ "message": "First name is required"
+ }
+ },
+ {
+ "name": "middleName",
+ "type": "string",
+ "label": "Father's middle name",
+ "required": false,
+ "validations": {
+ "max": 100,
+ "message": "Middle name is required"
+ }
+ },
+ {
+ "name": "lastName",
+ "type": "string",
+ "label": "Father's last name",
+ "required": false,
+ "validations": {
+ "min": 1,
+ "max": 100,
+ "message": "Last name is required"
+ }
+ }
+ ]
+ },
+ {
+ "name": "mother",
+ "type": "object",
+ "required": false,
+ "fields": [
+ {
+ "name": "firstName",
+ "type": "string",
+ "label": "Mother's first name",
+ "required": false,
+ "validations": {
+ "min": 1,
+ "max": 100,
+ "message": "First name is required"
+ }
+ },
+ {
+ "name": "middleName",
+ "type": "string",
+ "label": "Mother's middle name",
+ "required": false,
+ "validations": {
+ "max": 100,
+ "message": "Middle name is required"
+ }
+ },
+ {
+ "name": "lastName",
+ "type": "string",
+ "label": "Mother's last name",
+ "required": false,
+ "validations": {
+ "min": 1,
+ "max": 100,
+ "message": "Last name is required"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "order",
+ "type": "object",
+ "required": true,
+ "fields": [
+ {
+ "name": "numberOfCopies",
+ "type": "number",
+ "label": "Number of copies",
+ "required": true,
+ "validations": {
+ "min": 1,
+ "max": 10,
+ "message": "You must order at least 1 copy and maximum 10 copies"
+ }
+ }
+ ]
+ }
+ ],
+ "processors": [
+ {
+ "type": "payment",
+ "config": {
+ "provider": "ezpay",
+ "department": "revenue_authority",
+ "paymentCode": "{{db:get-birth-certificate:payment_code}}",
+ "amount": "{{formData.order.numberOfCopies * db:get-birth-certificate:payment_amount}}",
+ "description": "Birth Certificate Processing Fee (per copy)",
+ "required": true,
+ "timing": "after_validation",
+ "responseData": {
+ "include": ["order.numberOfCopies"]
+ }
+ }
+ },
+ {
+ "type": "email",
+ "config": {
+ "to": "{{db:get-birth-certificate:admin_email}}",
+ "subject": "New Birth Certificate Application - {{formData.applicant.firstName}} {{formData.applicant.lastName}}",
+ "template": "birth-certificate"
+ }
+ }
+ ]
}
diff --git a/schemas/get-death-certificate.json b/schemas/get-death-certificate.json
new file mode 100644
index 0000000..01b1d8a
--- /dev/null
+++ b/schemas/get-death-certificate.json
@@ -0,0 +1,293 @@
+{
+ "id": "get-death-certificate",
+ "name": "Get Death Certificate",
+ "description": "Apply for a copy of your death certificate or someone else's death certificate",
+ "fields": [
+ {
+ "name": "applicant",
+ "type": "object",
+ "required": true,
+ "fields": [
+ {
+ "name": "title",
+ "type": "string",
+ "label": "Title",
+ "required": true,
+ "validations": {
+ "regex": "^(mr|ms|mrs)$",
+ "message": "Must select a valid title"
+ }
+ },
+ {
+ "name": "firstName",
+ "type": "string",
+ "label": "First name",
+ "required": true,
+ "validations": {
+ "min": 1,
+ "max": 100,
+ "message": "First name is required"
+ }
+ },
+ {
+ "name": "middleName",
+ "type": "string",
+ "label": "Middle name",
+ "required": false,
+ "validations": {
+ "max": 100
+ }
+ },
+ {
+ "name": "lastName",
+ "type": "string",
+ "label": "Last name",
+ "required": true,
+ "validations": {
+ "min": 1,
+ "max": 100,
+ "message": "Last name is required"
+ }
+ },
+ {
+ "name": "addressLine1",
+ "type": "string",
+ "label": "Address Line 1",
+ "required": true,
+ "validations": {
+ "min": 5,
+ "max": 200,
+ "message": "Address must be at least 5 characters"
+ }
+ },
+ {
+ "name": "addressLine2",
+ "type": "string",
+ "label": "Address Line 2",
+ "required": false,
+ "validations": {
+ "max": 200
+ }
+ },
+ {
+ "name": "parish",
+ "type": "string",
+ "label": "Parish",
+ "required": true,
+ "validations": {
+ "regex": "^(christ-church|st-andrew|st-george|st-james|st-john|st-joseph|st-lucy|st-michael|st-peter|st-philip|st-thomas)$",
+ "message": "Must select a valid parish"
+ }
+ },
+ {
+ "name": "postalCode",
+ "type": "string",
+ "label": "Postal Code",
+ "required": false,
+ "validations": {
+ "regex": "^BB\\d{5}$",
+ "message": "Enter a valid postal code (e.g., BB17004)"
+ }
+ },
+ {
+ "name": "idNumber",
+ "type": "string",
+ "label": "National Identification (ID) Number",
+ "required": false,
+ "validations": {
+ "min": 2,
+ "message": "ID Number must be at least 2 characters"
+ }
+ },
+ {
+ "name": "passportNumber",
+ "type": "string",
+ "label": "Passport Number",
+ "required": false,
+ "validations": {
+ "message": "Passport number must be at least 6 characters"
+ }
+ },
+ {
+ "name": "email",
+ "type": "email",
+ "label": "Email Address",
+ "required": true
+ },
+ {
+ "name": "telephoneNumber",
+ "type": "string",
+ "label": "Telephone Number",
+ "required": true,
+ "validations": {
+ "regex": "^\\+?[0-9]{10,15}$",
+ "message": "Telephone number must be 10-15 digits"
+ }
+ }
+ ]
+ },
+ {
+ "name": "relationship",
+ "type": "string",
+ "label": "Tell us your relationship with the deceased",
+ "required": true,
+ "validations": {
+ "max": 100
+ }
+ },
+ {
+ "name": "reasonForRequest",
+ "type": "string",
+ "label": "Tell us about why you need this certificate",
+ "required": true,
+ "validations": {
+ "min": 1,
+ "max": 500
+ }
+ },
+ {
+ "name": "deceased",
+ "type": "object",
+ "required": true,
+ "fields": [
+ {
+ "name": "firstName",
+ "type": "string",
+ "label": "First name",
+ "required": true,
+ "validations": {
+ "min": 1,
+ "max": 100,
+ "message": "First name is required"
+ }
+ },
+ {
+ "name": "middleName",
+ "type": "string",
+ "label": "Middle name",
+ "required": false,
+ "validations": {
+ "max": 100
+ }
+ },
+ {
+ "name": "lastName",
+ "type": "string",
+ "label": "Last name",
+ "required": true,
+ "validations": {
+ "min": 1,
+ "max": 100,
+ "message": "Last name is required"
+ }
+ },
+ {
+ "name": "knownDateOfDeath",
+ "type": "string",
+ "label": "Do you know the date of death?",
+ "required": true,
+ "validations": {
+ "regex": "^(yes|no)$",
+ "message": "Must select an option"
+ }
+ },
+ {
+ "name": "dateOfDeath",
+ "type": "date",
+ "label": "Date of death",
+ "required": false,
+ "validations": {
+ "regex": "^\\d{4}-\\d{2}-\\d{2}$",
+ "message": "Date of death is required and must be in YYYY-MM-DD format"
+ }
+ },
+ {
+ "name": "estimatedDateOfDeath",
+ "type": "string",
+ "label": "Estimated date of death",
+ "required": false,
+ "validations": {
+ "max": 100,
+ "message": "Estimate is required"
+ }
+ },
+ {
+ "name": "idNumber",
+ "type": "string",
+ "label": "National Identification (ID) Number",
+ "required": false,
+ "validations": {
+ "min": 2,
+ "message": "ID Number must be at least 2 characters"
+ }
+ },
+ {
+ "name": "placeOfDeath",
+ "type": "string",
+ "label": "Place of death",
+ "required": true,
+ "validations": {
+ "min": 2,
+ "max": 200,
+ "message": "Place of death must be at least 2 characters"
+ }
+ },
+ {
+ "name": "causeOfDeath",
+ "type": "string",
+ "label": "Cause of death",
+ "required": true,
+ "validations": {
+ "min": 2,
+ "max": 200,
+ "message": "Cause of death must be at least 2 characters"
+ }
+ }
+ ]
+ },
+
+ {
+ "name": "order",
+ "type": "object",
+ "required": true,
+ "fields": [
+ {
+ "name": "numberOfCopies",
+ "type": "number",
+ "label": "Number of copies",
+ "required": true,
+ "validations": {
+ "min": 1,
+ "max": 10,
+ "message": "You must order at least 1 copy and maximum 10 copies"
+ }
+ }
+ ]
+ }
+ ],
+ "processors": [
+ {
+ "type": "payment",
+ "config": {
+ "provider": "ezpay",
+ "department": "revenue_authority",
+ "paymentCode": "{{db:get-death-certificate:payment_code}}",
+ "amount": "{{formData.order.numberOfCopies * db:get-death-certificate:payment_amount}}",
+ "description": "Death Certificate Processing Fee (per copy)",
+ "required": true,
+ "timing": "after_validation",
+ "responseData": {
+ "include": ["order.numberOfCopies"]
+ }
+ }
+ },
+ {
+ "type": "email",
+ "config": {
+ "to": "{{db:get-death-certificate:admin_email}}",
+ "subject": "New Death Certificate Application - {{formData.applicant.firstName}} {{formData.applicant.lastName}}",
+ "template": "death-certificate"
+ }
+ }
+ ]
+}
diff --git a/schemas/get-marriage-certificate.json b/schemas/get-marriage-certificate.json
new file mode 100644
index 0000000..ce80a9a
--- /dev/null
+++ b/schemas/get-marriage-certificate.json
@@ -0,0 +1,326 @@
+{
+ "id": "get-marriage-certificate",
+ "name": "Get Marriage Certificate",
+ "description": "Apply for a copy of your marriage certificate or someone else's marriage certificate",
+ "fields": [
+ {
+ "name": "applicant",
+ "type": "object",
+ "required": true,
+ "fields": [
+ {
+ "name": "title",
+ "type": "string",
+ "label": "Title",
+ "required": true,
+ "validations": {
+ "regex": "^(mr|ms|mrs)$",
+ "message": "Must select a valid title"
+ }
+ },
+ {
+ "name": "firstName",
+ "type": "string",
+ "label": "First name",
+ "required": true,
+ "validations": {
+ "min": 1,
+ "max": 100,
+ "message": "First name is required"
+ }
+ },
+ {
+ "name": "middleName",
+ "type": "string",
+ "label": "Middle name",
+ "required": false,
+ "validations": {
+ "max": 100
+ }
+ },
+ {
+ "name": "lastName",
+ "type": "string",
+ "label": "Last name",
+ "required": true,
+ "validations": {
+ "min": 1,
+ "max": 100,
+ "message": "Last name is required"
+ }
+ },
+ {
+ "name": "addressLine1",
+ "type": "string",
+ "label": "Address Line 1",
+ "required": true,
+ "validations": {
+ "min": 5,
+ "max": 200,
+ "message": "Address must be at least 5 characters"
+ }
+ },
+ {
+ "name": "addressLine2",
+ "type": "string",
+ "label": "Address Line 2",
+ "required": false,
+ "validations": {
+ "max": 200
+ }
+ },
+ {
+ "name": "parish",
+ "type": "string",
+ "label": "Parish",
+ "required": true,
+ "validations": {
+ "regex": "^(christ-church|st-andrew|st-george|st-james|st-john|st-joseph|st-lucy|st-michael|st-peter|st-philip|st-thomas)$",
+ "message": "Must select a valid parish"
+ }
+ },
+ {
+ "name": "postalCode",
+ "type": "string",
+ "label": "Postal Code",
+ "required": false,
+ "validations": {
+ "regex": "^BB\\d{5}$",
+ "message": "Enter a valid postal code (e.g., BB17004)"
+ }
+ },
+ {
+ "name": "idNumber",
+ "type": "string",
+ "label": "National Identification (ID) Number",
+ "required": false,
+ "validations": {
+ "min": 2,
+ "message": "ID Number must be at least 2 characters"
+ }
+ },
+ {
+ "name": "passportNumber",
+ "type": "string",
+ "label": "Passport Number",
+ "required": false,
+ "validations": {
+ "message": "Passport number must be at least 6 characters"
+ }
+ }
+ ]
+ },
+ {
+ "name": "applyingForYourself",
+ "type": "string",
+ "label": "Are you applying for your own marriage certificate?",
+ "required": true,
+ "validations": {
+ "regex": "^(yes|no)$",
+ "message": "Must select an option"
+ }
+ },
+ {
+ "name": "husband",
+ "type": "object",
+ "required": true,
+ "fields": [
+ {
+ "name": "firstName",
+ "type": "string",
+ "required": true,
+ "validations": {
+ "min": 1,
+ "max": 100
+ }
+ },
+ {
+ "name": "middleName",
+ "type": "string",
+ "required": false,
+ "validations": {
+ "max": 200
+ }
+ },
+ {
+ "name": "lastName",
+ "type": "string",
+ "required": true,
+ "validations": {
+ "min": 1,
+ "max": 100
+ }
+ },
+ {
+ "name": "idNumber",
+ "type": "string",
+ "label": "National Identification (ID) Number",
+ "required": false,
+ "validations": {
+ "min": 2,
+ "message": "ID Number must be at least 2 characters"
+ }
+ },
+ {
+ "name": "passportNumber",
+ "type": "string",
+ "label": "Passport Number",
+ "required": false,
+ "validations": {
+ "message": "Passport number must be at least 6 characters"
+ }
+ }
+ ]
+ },
+ {
+ "name": "wife",
+ "type": "object",
+ "required": true,
+ "fields": [
+ {
+ "name": "firstName",
+ "type": "string",
+ "required": true,
+ "validations": {
+ "min": 1,
+ "max": 100
+ }
+ },
+ {
+ "name": "middleName",
+ "type": "string",
+ "required": false,
+ "validations": {
+ "max": 200
+ }
+ },
+ {
+ "name": "maidenName",
+ "type": "string",
+ "required": true,
+ "validations": {
+ "min": 1,
+ "max": 100
+ }
+ },
+ {
+ "name": "idNumber",
+ "type": "string",
+ "label": "National Identification (ID) Number",
+ "required": false,
+ "validations": {
+ "min": 2,
+ "message": "ID Number must be at least 2 characters"
+ }
+ },
+ {
+ "name": "passportNumber",
+ "type": "string",
+ "label": "Passport Number",
+ "required": false,
+ "validations": {
+ "message": "Passport number must be at least 6 characters"
+ }
+ }
+ ]
+ },
+ {
+ "name": "marriageDetails",
+ "type": "object",
+ "required": true,
+ "fields": [
+ {
+ "name": "dateOfMarriage",
+ "type": "date",
+ "label": "Date of marriage",
+ "required": true,
+ "validations": {
+ "regex": "^\\d{4}-\\d{2}-\\d{2}$",
+ "message": "Date of marriage is required and must be in YYYY-MM-DD format"
+ }
+ },
+ {
+ "name": "placeOfMarriage",
+ "type": "string",
+ "label": "Place of marriage",
+ "required": true,
+ "validations": {
+ "min": 2,
+ "max": 200,
+ "message": "Place of marriage must be at least 2 characters"
+ }
+ }
+ ]
+ },
+ {
+ "name": "reason",
+ "type": "object",
+ "label": "Reason for Requesting a Marriage Certificate",
+ "required": false,
+ "fields": [
+ {
+ "name": "relationshipToMarriedPersons",
+ "type": "string",
+ "label": "Relationship",
+ "required": false,
+ "validations": {
+ "max": 100
+ }
+ },
+ {
+ "name": "explanationForRequestingCertificate",
+ "type": "string",
+ "label": "Why are you requesting the marriage certificate?",
+ "required": false,
+ "validations": {
+ "min": 1,
+ "max": 500
+ }
+ }
+ ]
+ },
+ {
+ "name": "order",
+ "type": "object",
+ "required": true,
+ "fields": [
+ {
+ "name": "numberOfCopies",
+ "type": "number",
+ "label": "Number of copies",
+ "required": true,
+ "validations": {
+ "min": 1,
+ "max": 10,
+ "message": "You must order at least 1 copy and maximum 10 copies"
+ }
+ }
+ ]
+ }
+ ],
+ "processors": [
+ {
+ "type": "payment",
+ "config": {
+ "provider": "ezpay",
+ "department": "revenue_authority",
+ "paymentCode": "{{db:get-marriage-certificate:payment_code}}",
+ "amount": "{{formData.order.numberOfCopies * db:get-marriage-certificate:payment_amount}}",
+ "description": "Marriage Certificate Processing Fee (per copy)",
+ "required": true,
+ "timing": "after_validation",
+ "responseData": {
+ "include": ["order.numberOfCopies"]
+ }
+ }
+ },
+ {
+ "type": "email",
+ "config": {
+ "to": "{{db:get-marriage-certificate:admin_email}}",
+ "subject": "New Marriage Certificate Application - {{formData.applicant.firstName}} {{formData.applicant.lastName}}",
+ "template": "marriage-certificate"
+ }
+ }
+ ]
+}
diff --git a/schemas/primary-school-textbook-grant.json b/schemas/primary-school-textbook-grant.json
index 9010b71..a81cd0e 100644
--- a/schemas/primary-school-textbook-grant.json
+++ b/schemas/primary-school-textbook-grant.json
@@ -228,17 +228,6 @@
}
],
"processors": [
- {
- "type": "payment",
- "config": {
- "provider": "ezpay",
- "paymentCode": "{{db:primary-school-textbook-grant:payment_code}}",
- "amount": 25.0,
- "description": "Processing Fee",
- "required": true,
- "timing": "after_validation"
- }
- },
{
"type": "email",
"config": {
diff --git a/src/app.module.ts b/src/app.module.ts
index 09812ca..4f8c86a 100644
--- a/src/app.module.ts
+++ b/src/app.module.ts
@@ -5,6 +5,7 @@ import { FormsModule } from './forms/forms.module';
import { ValidationModule } from './validation/validation.module';
import { ProcessorsModule } from './processors/processors.module';
import { EmailModule } from './email/email.module';
+import { FileModule } from './file/file.module';
@Module({
imports: [
@@ -14,6 +15,7 @@ import { EmailModule } from './email/email.module';
ValidationModule,
ProcessorsModule,
EmailModule,
+ FileModule,
],
controllers: [],
providers: [],
diff --git a/src/common/decorators/api-file.decorator.ts b/src/common/decorators/api-file.decorator.ts
new file mode 100644
index 0000000..30311f4
--- /dev/null
+++ b/src/common/decorators/api-file.decorator.ts
@@ -0,0 +1,6 @@
+import { applyDecorators, UseInterceptors } from '@nestjs/common';
+import { FileInterceptor } from '@nestjs/platform-express';
+
+export function ApiFile(fieldName = 'file') {
+ return applyDecorators(UseInterceptors(FileInterceptor(fieldName)));
+}
diff --git a/src/common/decorators/index.ts b/src/common/decorators/index.ts
new file mode 100644
index 0000000..73ad553
--- /dev/null
+++ b/src/common/decorators/index.ts
@@ -0,0 +1 @@
+export * from './api-file.decorator';
diff --git a/src/common/dto/attachment.dto.ts b/src/common/dto/attachment.dto.ts
new file mode 100644
index 0000000..472931b
--- /dev/null
+++ b/src/common/dto/attachment.dto.ts
@@ -0,0 +1,7 @@
+export class AttachmentDTO {
+ url: string;
+ key: string;
+ type: string;
+ name: string;
+ size: number;
+}
diff --git a/src/common/dto/index.ts b/src/common/dto/index.ts
index f77a035..b6b0b6c 100644
--- a/src/common/dto/index.ts
+++ b/src/common/dto/index.ts
@@ -1 +1,2 @@
export * from './api-response.dto';
+export * from './attachment.dto';
diff --git a/src/common/pipes/index.ts b/src/common/pipes/index.ts
index dbc04f8..30ce9f6 100644
--- a/src/common/pipes/index.ts
+++ b/src/common/pipes/index.ts
@@ -1 +1,2 @@
export * from './validation.pipe';
+export * from './parse-file.pipe';
diff --git a/src/common/pipes/parse-file.pipe.ts b/src/common/pipes/parse-file.pipe.ts
new file mode 100644
index 0000000..79a32a3
--- /dev/null
+++ b/src/common/pipes/parse-file.pipe.ts
@@ -0,0 +1,19 @@
+import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common';
+
+@Injectable()
+export class ParseFile implements PipeTransform {
+ transform(file: Express.Multer.File): Express.Multer.File {
+ if (!file) {
+ throw new BadRequestException('File is required');
+ }
+
+ const maxSize = 10 * 1024 * 1024; // 10MB
+ if (file.size > maxSize) {
+ throw new BadRequestException(
+ `File size exceeds maximum limit of ${maxSize / 1024 / 1024}MB`,
+ );
+ }
+
+ return file;
+ }
+}
diff --git a/src/config/configuration.ts b/src/config/configuration.ts
index 70e7faa..221ede6 100644
--- a/src/config/configuration.ts
+++ b/src/config/configuration.ts
@@ -22,6 +22,11 @@ export default () => ({
tagKey: process.env.SES_TAG_KEY || 'ses:configuration-set',
tagValue: process.env.SES_TAG_VALUE || 'prod',
},
+ s3: {
+ bucketName: process.env.BUCKET_NAME,
+ bucketRegion:
+ process.env.BUCKET_REGION || process.env.AWS_REGION || 'us-east-1',
+ },
},
email: {
templatesDir: process.env.EMAIL_TEMPLATES_DIR || 'src/email/templates',
@@ -30,8 +35,24 @@ export default () => ({
schemasDir: process.env.FORM_SCHEMAS_DIR || 'schemas',
},
ezpay: {
- apiKey: process.env.EZPAY_API_KEY || 'HWqgTn5EXIHLAzVjXtGpB2mIjgQgj0Ql',
+ apiKey: process.env.EZPAY_API_KEY || 'HWqgTn5EXIHLAzVjXtGpB2mIjgQgj0Ql', // Default API key for backward compatibility
baseUrl: process.env.EZPAY_BASE_URL || 'https://test.ezpay.gov.bb',
webhookSecret: process.env.EZPAY_WEBHOOK_SECRET,
+ // Department-specific API keys
+ departmentApiKeys: {
+ ministry_of_youth: process.env.EZPAY_MINISTRY_OF_YOUTH_API_KEY,
+ town_and_country: process.env.EZPAY_TOWN_AND_COUNTRY_API_KEY,
+ licensing_authority: process.env.EZPAY_LICENSING_AUTHORITY_API_KEY,
+ immigration_department: process.env.EZPAY_IMMIGRATION_DEPARTMENT_API_KEY,
+ ministry_of_transport_and_works:
+ process.env.EZPAY_MINISTRY_OF_TRANSPORT_AND_WORKS_API_KEY,
+ government_electrical_engineering_department:
+ process.env.EZPAY_GOVERNMENT_ELECTRICAL_ENGINEERING_DEPARTMENT_API_KEY,
+ revenue_authority: process.env.EZPAY_REVENUE_AUTHORITY_API_KEY,
+ ministry_of_agriculture:
+ process.env.EZPAY_MINISTRY_OF_AGRICULTURE_API_KEY,
+ oag_registration: process.env.EZPAY_OAG_REGISTRATION_API_KEY,
+ default: process.env.EZPAY_API_KEY || 'HWqgTn5EXIHLAzVjXtGpB2mIjgQgj0Ql',
+ },
},
});
diff --git a/src/email/templates/death-certificate.hbs b/src/email/templates/death-certificate.hbs
new file mode 100644
index 0000000..07e22a6
--- /dev/null
+++ b/src/email/templates/death-certificate.hbs
@@ -0,0 +1,208 @@
+
+
+
+
+
+
+
+
New Death Certificate Application
+
+
+ Application Submitted:
+ {{processedAt}}
+ Application Type:
+ {{#if (eq applyingForYourself 'yes')}}
+ Self Application
+ {{else}}
+ Third Party Application
+ {{/if}}
+
+
+
+
+ Applicant Information
+
+
+ {{#if applicant.title}}
+
+ | Title: |
+ {{#if (eq applicant.title 'mr')}}Mr{{else if
+ (eq applicant.title 'ms')
+ }}Ms{{else if
+ (eq applicant.title 'mrs')
+ }}Mrs{{else}}{{applicant.title}}{{/if}} |
+
+ {{/if}}
+ {{#if applicant.firstName}}
+
+ | First Name: |
+ {{applicant.firstName}} |
+
+ {{/if}}
+ {{#if applicant.middleName}}
+
+ | Middle Name: |
+ {{applicant.middleName}} |
+
+ {{/if}}
+ {{#if applicant.lastName}}
+
+ | Last Name: |
+ {{applicant.lastName}} |
+
+ {{/if}}
+ {{#if applicant.email}}
+
+ | Email: |
+ {{applicant.email}} |
+
+ {{/if}}
+ {{#if applicant.phoneNumber}}
+
+ | Phone Number: |
+ {{applicant.phoneNumber}} |
+
+ {{/if}}
+
+
+
+ Address
+
+
+ {{#if applicant.addressLine1}}
+
+ | Address Line 1: |
+ {{applicant.addressLine1}} |
+
+ {{/if}}
+ {{#if applicant.addressLine2}}
+
+ | Address Line 2: |
+ {{applicant.addressLine2}} |
+
+ {{/if}}
+ {{#if applicant.parish}}
+
+ | Parish: |
+ {{applicant.parish}} |
+
+ {{/if}}
+ {{#if applicant.postalCode}}
+
+ | Postal Code: |
+ {{applicant.postalCode}} |
+
+ {{/if}}
+
+
+
+ Identification
+
+
+ {{#if applicant.usePassportInstead}}
+ {{#if applicant.passportNumber}}
+
+ | Passport Number: |
+ {{applicant.passportNumber}} |
+
+ {{/if}}
+ {{else}}
+ {{#if applicant.idNumber}}
+
+ | National ID Number: |
+ {{applicant.idNumber}} |
+
+ {{/if}}
+ {{/if}}
+
+
+
+
+
+
+ Deceased Information
+
+
+ {{#if deceased.firstName}}
+
+ | First Name: |
+ {{deceased.firstName}} |
+
+ {{/if}}
+ {{#if deceased.middleName}}
+
+ | Middle Name: |
+ {{deceased.middleName}} |
+
+ {{/if}}
+ {{#if deceased.lastName}}
+
+ | Last Name: |
+ {{deceased.lastName}} |
+
+ {{/if}}
+ {{#if deceased.dateOfBirth}}
+
+ | Date of Birth: |
+ {{deceased.dateOfBirth}} |
+
+ {{/if}}
+ {{#if deceased.placeOfDeath}}
+
+ | Place of Death: |
+ {{deceased.placeOfDeath}} |
+
+ {{/if}}
+ {{#if deceased.causeOfDeath}}
+
+ | Cause of Death: |
+ {{deceased.causeOfDeath}} |
+
+ {{/if}}
+
+
+
+
+
+
+ Order Information
+
+ Number of Copies Requested:
+ {{order.numberOfCopies}}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/email/templates/marriage-certificate.hbs b/src/email/templates/marriage-certificate.hbs
new file mode 100644
index 0000000..406855b
--- /dev/null
+++ b/src/email/templates/marriage-certificate.hbs
@@ -0,0 +1,208 @@
+
+
+
+
+
+
+
+
New Marriage Certificate Application
+
+
+ Application Submitted:
+ {{processedAt}}
+ Application Type:
+ {{#if (eq applyingForYourself 'yes')}}
+ Self Application
+ {{else}}
+ Third Party Application
+ {{/if}}
+
+
+
+
+ Applicant Information
+
+
+ {{#if applicant.title}}
+
+ | Title: |
+ {{#if (eq applicant.title 'mr')}}Mr{{else if
+ (eq applicant.title 'ms')
+ }}Ms{{else if
+ (eq applicant.title 'mrs')
+ }}Mrs{{else}}{{applicant.title}}{{/if}} |
+
+ {{/if}}
+ {{#if applicant.firstName}}
+
+ | First Name: |
+ {{applicant.firstName}} |
+
+ {{/if}}
+ {{#if applicant.middleName}}
+
+ | Middle Name: |
+ {{applicant.middleName}} |
+
+ {{/if}}
+ {{#if applicant.lastName}}
+
+ | Last Name: |
+ {{applicant.lastName}} |
+
+ {{/if}}
+ {{#if applicant.email}}
+
+ | Email: |
+ {{applicant.email}} |
+
+ {{/if}}
+ {{#if applicant.phoneNumber}}
+
+ | Phone Number: |
+ {{applicant.phoneNumber}} |
+
+ {{/if}}
+
+
+
+ Address
+
+
+ {{#if applicant.addressLine1}}
+
+ | Address Line 1: |
+ {{applicant.addressLine1}} |
+
+ {{/if}}
+ {{#if applicant.addressLine2}}
+
+ | Address Line 2: |
+ {{applicant.addressLine2}} |
+
+ {{/if}}
+ {{#if applicant.parish}}
+
+ | Parish: |
+ {{applicant.parish}} |
+
+ {{/if}}
+ {{#if applicant.postalCode}}
+
+ | Postal Code: |
+ {{applicant.postalCode}} |
+
+ {{/if}}
+
+
+
+ Identification
+
+
+ {{#if applicant.usePassportInstead}}
+ {{#if applicant.passportNumber}}
+
+ | Passport Number: |
+ {{applicant.passportNumber}} |
+
+ {{/if}}
+ {{else}}
+ {{#if applicant.idNumber}}
+
+ | National ID Number: |
+ {{applicant.idNumber}} |
+
+ {{/if}}
+ {{/if}}
+
+
+
+
+
+
+ Parents' Information
+
+ {{#if parents.father}}
+ Father
+
+
+ {{#if parents.father.firstName}}
+
+ | First Name: |
+ {{parents.father.firstName}} |
+
+ {{/if}}
+ {{#if parents.father.lastName}}
+
+ | Last Name: |
+ {{parents.father.lastName}} |
+
+ {{/if}}
+
+
+ {{/if}}
+
+ {{#if parents.mother}}
+ Mother
+
+
+ {{#if parents.mother.firstName}}
+
+ | First Name: |
+ {{parents.mother.firstName}} |
+
+ {{/if}}
+ {{#if parents.mother.lastName}}
+
+ | Last Name: |
+ {{parents.mother.lastName}} |
+
+ {{/if}}
+
+
+ {{/if}}
+
+
+
+
+ Order Information
+
+ Number of Copies Requested:
+ {{order.numberOfCopies}}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/file/file.controller.ts b/src/file/file.controller.ts
new file mode 100644
index 0000000..77b894d
--- /dev/null
+++ b/src/file/file.controller.ts
@@ -0,0 +1,27 @@
+import {
+ Controller,
+ Post,
+ Get,
+ Query,
+ UploadedFile,
+ BadRequestException,
+} from '@nestjs/common';
+import { ApiFile } from '../common/decorators';
+import { ParseFile } from '../common/pipes';
+import { ApiResponse } from '../common/dto';
+import { FileService } from './file.service';
+
+@Controller('file')
+export class FileController {
+ constructor(private readonly filesService: FileService) {}
+
+ @Post('upload')
+ @ApiFile('file')
+ async uploadFile(
+ @UploadedFile(ParseFile) file: Express.Multer.File,
+ @Query('folder') folder?: string,
+ ) {
+ const data = await this.filesService.uploadFile(file, folder);
+ return ApiResponse.success(data, 'File uploaded successfully');
+ }
+}
diff --git a/src/file/file.module.ts b/src/file/file.module.ts
new file mode 100644
index 0000000..a0258d5
--- /dev/null
+++ b/src/file/file.module.ts
@@ -0,0 +1,12 @@
+import { Module } from '@nestjs/common';
+import { ConfigModule } from '@nestjs/config';
+import { FileService } from './file.service';
+import { FileController } from './file.controller';
+
+@Module({
+ imports: [ConfigModule],
+ providers: [FileService],
+ controllers: [FileController],
+ exports: [FileService],
+})
+export class FileModule {}
diff --git a/src/file/file.service.ts b/src/file/file.service.ts
new file mode 100644
index 0000000..0832eb4
--- /dev/null
+++ b/src/file/file.service.ts
@@ -0,0 +1,82 @@
+import { Injectable } from '@nestjs/common';
+import { ConfigService } from '@nestjs/config';
+import { Upload } from '@aws-sdk/lib-storage';
+import {
+ PutObjectCommandInput,
+ S3Client,
+ GetObjectCommand,
+} from '@aws-sdk/client-s3';
+import * as S3Presigner from '@aws-sdk/s3-request-presigner';
+import { AttachmentDTO } from '../common/dto';
+
+@Injectable()
+export class FileService {
+ constructor(private configService: ConfigService) {}
+
+ async uploadFile(
+ file: Express.Multer.File,
+ folder = 'general',
+ ): Promise {
+ const result = await this.aws(file, folder.toLowerCase());
+
+ if (!result.url) {
+ throw new Error('File upload failed');
+ }
+
+ return {
+ url: result.url,
+ key: result.key,
+ type: file.mimetype,
+ name: file.originalname,
+ size: file.size,
+ };
+ }
+
+ private async aws(
+ file: Express.Multer.File,
+ folder = 'general',
+ ): Promise<{ url: string; key: string }> {
+ const s3 = new S3Client({
+ region: this.configService.get('aws.s3.bucketRegion'),
+ });
+
+ const fileName = `${folder}/${Date.now()}-${file.originalname}`.replace(
+ /\s/g,
+ '_',
+ );
+
+ const params: PutObjectCommandInput = {
+ Bucket: this.configService.get('aws.s3.bucketName'),
+ Key: fileName,
+ Body: file.buffer,
+ };
+
+ await new Upload({
+ client: s3,
+ params,
+ }).done();
+
+ const url = await this.getSignedUrl(fileName, 7 * 24 * 3600); // 7 days
+
+ return {
+ url,
+ key: fileName,
+ };
+ }
+
+ private async getSignedUrl(
+ fileKey: string,
+ expiresIn = 3600,
+ ): Promise {
+ const s3 = new S3Client({
+ region: this.configService.get('aws.s3.bucketRegion'),
+ });
+
+ const command = new GetObjectCommand({
+ Bucket: this.configService.get('aws.s3.bucketName'),
+ Key: fileKey,
+ });
+
+ return S3Presigner.getSignedUrl(s3, command, { expiresIn });
+ }
+}
diff --git a/src/forms/dto/form-submission-response.dto.ts b/src/forms/dto/form-submission-response.dto.ts
index 9449640..087b19a 100644
--- a/src/forms/dto/form-submission-response.dto.ts
+++ b/src/forms/dto/form-submission-response.dto.ts
@@ -13,6 +13,9 @@ export class FormSubmissionResponseDto {
amount?: number;
description?: string;
+ // Dynamic additional data
+ [key: string]: any;
+
constructor(
submissionId: string,
formId: string,
@@ -26,6 +29,7 @@ export class FormSubmissionResponseDto {
amount?: number;
description?: string;
},
+ additionalData?: Record,
) {
this.submissionId = submissionId;
this.formId = formId;
@@ -41,5 +45,10 @@ export class FormSubmissionResponseDto {
this.amount = paymentInfo.amount;
this.description = paymentInfo.description;
}
+
+ // Add any additional dynamic data
+ if (additionalData) {
+ Object.assign(this, additionalData);
+ }
}
}
diff --git a/src/forms/expression-resolver.service.ts b/src/forms/expression-resolver.service.ts
new file mode 100644
index 0000000..869177d
--- /dev/null
+++ b/src/forms/expression-resolver.service.ts
@@ -0,0 +1,326 @@
+import { Injectable, Logger } from '@nestjs/common';
+import { ConfigService } from '@nestjs/config';
+import { Repository } from 'typeorm';
+import { FormConfig } from '../database/entities';
+
+export interface ExpressionContext {
+ formId: string;
+ formData?: Record;
+ secrets?: Map;
+ configRepository?: Repository;
+}
+
+@Injectable()
+export class ExpressionResolverService {
+ private readonly logger = new Logger(ExpressionResolverService.name);
+
+ constructor(private readonly configService: ConfigService) {}
+
+ /**
+ * Resolve any expression with support for:
+ * - Database secrets: {{db:form-id:key}} or {{db:key}}
+ * - Form data references: {{formData.path}}
+ * - Mathematical expressions: {{formData.field * db:form-id:amount}}
+ * - Simple values: direct strings or numbers
+ */
+ async resolveExpression(
+ expression: string | number,
+ context: ExpressionContext,
+ ): Promise {
+ // If it's not a string, return as-is
+ if (typeof expression !== 'string') {
+ return expression;
+ }
+
+ // If it doesn't contain expression markers, return as-is
+ if (!expression.includes('{{') || !expression.includes('}}')) {
+ return expression;
+ }
+
+ // Handle complex expressions (mathematical operations)
+ if (this.isMathematicalExpression(expression)) {
+ return await this.resolveMathematicalExpression(expression, context);
+ }
+
+ // Handle simple variable replacement
+ return await this.resolveSimpleExpression(expression, context);
+ }
+
+ /**
+ * Check if expression contains mathematical operators
+ */
+ private isMathematicalExpression(expression: string): boolean {
+ // Extract content between {{ and }}
+ const match = expression.match(/^\{\{(.+)\}\}$/);
+ if (!match) {
+ return false;
+ }
+
+ const content = match[1];
+ // Look for mathematical operators with proper spacing or clear mathematical context
+ // This is more specific to avoid matching hyphens in identifiers like "get-birth-certificate"
+ const pattern1 = /\s+[+\-*/]\s+/.test(content); // operators with spaces on both sides
+ const pattern2 = /formData\.[a-zA-Z0-9_.]+\s*[+\-*/]\s*/.test(content); // formData followed by operator
+ const pattern3 = /[+\-*/]\s*formData\./.test(content); // operator followed by formData
+ const pattern4 = /[+\-*/]\s*db:/.test(content); // operator followed by db reference
+ const pattern5 = /\)\s*[+\-*/]\s*/.test(content); // operator after closing parenthesis
+ const pattern6 = /\s*[+\-*/]\s*\(/.test(content); // operator before opening parenthesis
+
+ const hasMathOperators =
+ pattern1 || pattern2 || pattern3 || pattern4 || pattern5 || pattern6;
+
+ return hasMathOperators;
+ }
+
+ /**
+ * Resolve mathematical expressions like {{formData.numberOfCopies * db:form-id:amount}}
+ */
+ private async resolveMathematicalExpression(
+ expression: string,
+ context: ExpressionContext,
+ ): Promise {
+ // Extract the inner expression
+ const match = expression.match(/^\{\{(.+)\}\}$/);
+ if (!match) {
+ throw new Error(`Invalid expression format: ${expression}`);
+ }
+
+ let mathExpression = match[1];
+
+ // Replace database references first
+ mathExpression = await this.replaceDatabaseReferences(
+ mathExpression,
+ context,
+ );
+
+ // Replace form data references
+ mathExpression = this.replaceFormDataReferences(mathExpression, context);
+
+ // Evaluate the mathematical expression
+ return this.evaluateMathExpression(mathExpression);
+ }
+
+ /**
+ * Resolve simple expressions like {{db:key}} or {{formData.field}}
+ */
+ private async resolveSimpleExpression(
+ expression: string,
+ context: ExpressionContext,
+ ): Promise {
+ // Extract the inner expression
+ const match = expression.match(/^\{\{(.+)\}\}$/);
+ if (!match) {
+ return expression; // Return as-is if not a proper expression
+ }
+
+ let innerExpression = match[1];
+
+ // Replace database secrets in the inner expression
+ innerExpression = await this.replaceDatabaseReferences(
+ innerExpression,
+ context,
+ );
+
+ // Replace form data references in the inner expression
+ innerExpression = this.replaceFormDataReferences(innerExpression, context);
+
+ return innerExpression; // Return the resolved inner content without {{}}
+ }
+
+ /**
+ * Replace database references in expression
+ */
+ private async replaceDatabaseReferences(
+ expression: string,
+ context: ExpressionContext,
+ ): Promise {
+ // Match patterns like db:form-id:key or db:key
+ const dbPattern = /db:([^:]+)(?::([^}\s+\-*/()]+))?/g;
+ let result = expression;
+
+ const matches = [...expression.matchAll(dbPattern)];
+ for (const match of matches) {
+ const [fullMatch, part1, part2] = match;
+ let formId: string;
+ let secretKey: string;
+
+ if (part2) {
+ // Format: db:form-id:key
+ formId = part1;
+ secretKey = part2;
+ } else {
+ // Format: db:key (use current form ID)
+ formId = context.formId;
+ secretKey = part1;
+ }
+
+ try {
+ const secretValue = await this.getSecretValue(
+ formId,
+ secretKey,
+ context,
+ );
+ result = result.replace(fullMatch, secretValue);
+ } catch (error) {
+ this.logger.warn(
+ `Failed to resolve database reference ${fullMatch}:`,
+ error.message,
+ );
+ // Replace with empty string or default value
+ result = result.replace(fullMatch, '0');
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Replace form data references in expression
+ */
+ private replaceFormDataReferences(
+ expression: string,
+ context: ExpressionContext,
+ ): string {
+ if (!context.formData) {
+ return expression;
+ }
+
+ // Match patterns like formData.field.path
+ const formDataPattern = /formData\.([a-zA-Z0-9._]+)/g;
+ let result = expression;
+
+ const matches = [...expression.matchAll(formDataPattern)];
+ for (const match of matches) {
+ const [fullMatch, fieldPath] = match;
+ const value = this.getNestedValue(context.formData, fieldPath);
+
+ if (value !== undefined && value !== null) {
+ result = result.replace(fullMatch, String(value));
+ } else {
+ this.logger.warn(`Form data field not found: ${fieldPath}`);
+ result = result.replace(fullMatch, '0');
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Get secret value from database repository or environment variables
+ */
+ private async getSecretValue(
+ formId: string,
+ secretKey: string,
+ context: ExpressionContext,
+ ): Promise {
+ // Try database repository first if available
+ if (context.configRepository) {
+ try {
+ const config = await context.configRepository.findOne({
+ where: { formId, key: secretKey },
+ });
+
+ if (config) {
+ return config.value;
+ }
+ } catch (error) {
+ this.logger.warn(
+ `Error querying database for secret ${formId}:${secretKey}:`,
+ error.message,
+ );
+ }
+ }
+
+ // Fallback to secrets Map if provided
+ if (context.secrets) {
+ const secretMapKey = `${formId}:${secretKey}`;
+ const value = context.secrets.get(secretMapKey);
+ if (value) {
+ return value;
+ }
+ }
+
+ // Final fallback to environment variables
+ const envKey = `${formId
+ .toUpperCase()
+ .replace(/-/g, '_')}_${secretKey.toUpperCase()}`;
+
+ const value = this.configService.get(envKey);
+ if (value) {
+ return value;
+ }
+
+ throw new Error(
+ `Secret not found: ${formId}:${secretKey} (tried database, secrets map, and env ${envKey})`,
+ );
+ }
+
+ /**
+ * Safely evaluate mathematical expression
+ */
+ private evaluateMathExpression(expression: string): number {
+ // Validate that expression only contains safe characters
+ if (!/^[\d\s+\-*/.()]+$/.test(expression)) {
+ throw new Error(`Unsafe mathematical expression: ${expression}`);
+ }
+
+ try {
+ // Use Function constructor for safe evaluation
+ const result = new Function('return ' + expression)();
+ const numericResult = Number(result);
+
+ if (isNaN(numericResult)) {
+ throw new Error(`Invalid calculation result: ${result}`);
+ }
+
+ return numericResult;
+ } catch (error) {
+ this.logger.error(
+ `Failed to evaluate expression ${expression}:`,
+ error.message,
+ );
+ return 0;
+ }
+ }
+
+ /**
+ * Get nested value from object using dot notation
+ */
+ private getNestedValue(obj: any, path: string): any {
+ return path.split('.').reduce((current, key) => {
+ return current && typeof current === 'object' ? current[key] : undefined;
+ }, obj);
+ }
+
+ /**
+ * Recursively resolve all expressions in an object
+ */
+ async resolveObjectExpressions(
+ obj: any,
+ context: ExpressionContext,
+ ): Promise {
+ if (obj === null || obj === undefined) {
+ return obj;
+ }
+
+ if (Array.isArray(obj)) {
+ return Promise.all(
+ obj.map((item) => this.resolveObjectExpressions(item, context)),
+ );
+ }
+
+ if (typeof obj === 'object') {
+ const resolved: any = {};
+ for (const [key, value] of Object.entries(obj)) {
+ resolved[key] = await this.resolveObjectExpressions(value, context);
+ }
+ return resolved;
+ }
+
+ if (typeof obj === 'string' || typeof obj === 'number') {
+ return await this.resolveExpression(obj, context);
+ }
+
+ return obj;
+ }
+}
diff --git a/src/forms/form-utils.service.ts b/src/forms/form-utils.service.ts
index b0fdf87..69033d7 100644
--- a/src/forms/form-utils.service.ts
+++ b/src/forms/form-utils.service.ts
@@ -11,6 +11,7 @@ import * as fs from 'fs/promises';
import * as path from 'path';
import { FormConfig } from '../database/entities';
import { FormSchema } from './interfaces';
+import { ExpressionResolverService } from './expression-resolver.service';
@Injectable()
export class FormUtilsService implements OnModuleInit {
@@ -22,6 +23,7 @@ export class FormUtilsService implements OnModuleInit {
@InjectRepository(FormConfig)
private readonly formConfigRepository: Repository,
private readonly configService: ConfigService,
+ private readonly expressionResolver: ExpressionResolverService,
) {
this.schemasDir = path.join(
process.cwd(),
@@ -86,162 +88,23 @@ export class FormUtilsService implements OnModuleInit {
): Promise {
const schema = this.getSchema(formId);
- // Replace secret variables and form data in processor configs
+ // Use centralized expression resolver for processor configs
+ const context = {
+ formId,
+ formData: formData || {},
+ configRepository: this.formConfigRepository,
+ };
+
for (const processor of schema.processors) {
- processor.config = await this.replaceVariables(
- formId,
+ processor.config = await this.expressionResolver.resolveObjectExpressions(
processor.config,
- formData,
+ context,
);
}
return schema;
}
- /**
- * Replace all variable patterns (database secrets and form data) in a config object
- */
- private async replaceVariables(
- formId: string,
- config: Record,
- formData?: Record,
- ): Promise> {
- const result = { ...config };
-
- for (const [key, value] of Object.entries(result)) {
- if (typeof value === 'string') {
- result[key] = await this.replaceVariableValue(formId, value, formData);
- } else if (typeof value === 'object' && value !== null) {
- result[key] = await this.replaceVariables(formId, value, formData);
- }
- }
-
- return result;
- }
-
- /**
- * Replace both database secrets and form data variables in a string value
- * Supports:
- * - {{db:key}} or {{db:formId:key}} for database secrets
- * - {{formData.fieldName}} for form field values
- */
- private async replaceVariableValue(
- formId: string,
- value: string,
- formData?: Record,
- ): Promise {
- let result = value;
-
- // Replace database secrets: {{db:key}} or {{db:formId:key}}
- result = await this.replaceDbSecrets(formId, result);
-
- // Replace form data variables: {{formData.fieldName}}
- if (formData) {
- result = this.replaceFormData(result, formData);
- }
-
- return result;
- }
-
- /**
- * Replace database secret patterns in a string
- */
- private async replaceDbSecrets(
- formId: string,
- value: string,
- ): Promise {
- const regex = /\{\{db:([^}]+)\}\}/g;
- let result = value;
-
- const matches = value.matchAll(regex);
- for (const match of matches) {
- const parts = match[1].split(':');
- let targetFormId: string;
- let targetKey: string;
-
- if (parts.length === 1) {
- // Shorthand: {{db:key}} - use current formId
- targetFormId = formId;
- targetKey = parts[0];
- } else {
- // Full format: {{db:formId:key}}
- targetFormId = parts[0];
- targetKey = parts[1];
- }
-
- const secretValue = await this.getSecret(targetFormId, targetKey);
- result = result.replace(match[0], secretValue);
- }
-
- return result;
- }
-
- /**
- * Replace form data patterns in a string
- * Supports: {{formData.fieldName}} and nested paths like {{formData.nested.keyName}}
- */
- private replaceFormData(
- value: string,
- formData: Record,
- ): string {
- const regex = /\{\{formData\.([^}]+)\}\}/g;
- let result = value;
-
- const matches = value.matchAll(regex);
- for (const match of matches) {
- const fieldPath = match[1];
- const fieldValue = this.getNestedValue(formData, fieldPath);
-
- if (fieldValue !== undefined && fieldValue !== null) {
- // Convert to string and replace
- result = result.replace(match[0], String(fieldValue));
- } else {
- this.logger.warn(
- `Form data field not found: ${fieldPath}, removing from string`,
- );
- // Remove the placeholder if field not found
- result = result.replace(match[0], '');
- }
- }
-
- return result;
- }
-
- /**
- * Get a nested value from an object using a dot-separated path
- * Example: getNestedValue({child: {firstName: 'John'}}, 'child.firstName') => 'John'
- */
- private getNestedValue(obj: Record, path: string): any {
- const keys = path.split('.');
- let current = obj;
-
- for (const key of keys) {
- if (current && typeof current === 'object' && key in current) {
- current = current[key];
- } else {
- return undefined;
- }
- }
-
- return current;
- }
-
- /**
- * Retrieve a secret value from the database
- */
- private async getSecret(formId: string, key: string): Promise {
- const config = await this.formConfigRepository.findOne({
- where: { formId, key },
- });
-
- if (!config) {
- this.logger.warn(`Secret not found: ${formId}:${key}`);
- return `{{db:${formId}:${key}}}`; // Return placeholder if not found
- }
-
- return config.value;
- }
-
/**
* Reload all form schemas from disk
*/
diff --git a/src/forms/forms.module.ts b/src/forms/forms.module.ts
index c6489f7..193c700 100644
--- a/src/forms/forms.module.ts
+++ b/src/forms/forms.module.ts
@@ -5,11 +5,12 @@ import { ProcessorsModule } from '../processors/processors.module';
import { FormsController } from './forms.controller';
import { FormsService } from './forms.service';
import { FormUtilsService } from './form-utils.service';
+import { ExpressionResolverService } from './expression-resolver.service';
@Module({
imports: [DatabaseModule, ValidationModule, ProcessorsModule],
controllers: [FormsController],
- providers: [FormsService, FormUtilsService],
- exports: [FormsService, FormUtilsService],
+ providers: [FormsService, FormUtilsService, ExpressionResolverService],
+ exports: [FormsService, FormUtilsService, ExpressionResolverService],
})
export class FormsModule {}
diff --git a/src/forms/forms.service.ts b/src/forms/forms.service.ts
index 3aa678c..434a2c2 100644
--- a/src/forms/forms.service.ts
+++ b/src/forms/forms.service.ts
@@ -173,6 +173,7 @@ export class FormsService {
amount: paymentProcessor.config.amount,
description: paymentProcessor.config.description,
},
+ paymentResult.additionalData,
);
return {
diff --git a/src/forms/interfaces/form-schema.interface.ts b/src/forms/interfaces/form-schema.interface.ts
index 702badb..9556d6f 100644
--- a/src/forms/interfaces/form-schema.interface.ts
+++ b/src/forms/interfaces/form-schema.interface.ts
@@ -57,6 +57,7 @@ export interface PaymentProcessorConfig extends ProcessorConfig {
type: 'payment';
config: {
provider: 'ezpay';
+ department: string; // Department name (education, health, social_services, transport, etc.)
paymentCode: string; // EZPay+ payment code (stored in secrets)
amount: number | string; // Fixed amount or formula like "{{formData.calculatedFee}}"
description: string;
@@ -65,5 +66,10 @@ export interface PaymentProcessorConfig extends ProcessorConfig {
allowPayce?: boolean;
required?: boolean; // Whether payment is mandatory for form submission
timing?: 'immediate' | 'after_validation'; // When to create payment
+ responseData?: ResponseDataConfig; // Additional data to include in response
};
}
+
+export interface ResponseDataConfig {
+ include?: string[]; // Form field paths to include (e.g., ['order.numberOfCopies', 'applicant.email'])
+}
diff --git a/src/payments/department-mapping.service.ts b/src/payments/department-mapping.service.ts
new file mode 100644
index 0000000..6036c3a
--- /dev/null
+++ b/src/payments/department-mapping.service.ts
@@ -0,0 +1,62 @@
+import { Injectable, Logger } from '@nestjs/common';
+import { ConfigService } from '@nestjs/config';
+
+@Injectable()
+export class DepartmentMappingService {
+ private readonly logger = new Logger(DepartmentMappingService.name);
+
+ constructor(private configService: ConfigService) {}
+
+ /**
+ * Get the API key for a given department
+ */
+ getApiKeyForDepartment(department: string): string {
+ const departmentApiKeys = this.configService.get('ezpay.departmentApiKeys');
+
+ if (!departmentApiKeys) {
+ this.logger.warn(
+ 'Department API keys not configured, falling back to default',
+ );
+ return this.configService.get('ezpay.apiKey');
+ }
+
+ const apiKey = departmentApiKeys[department];
+
+ if (!apiKey) {
+ this.logger.warn(
+ `No API key configured for department: ${department}, using default`,
+ );
+ return (
+ departmentApiKeys.default ||
+ this.configService.get('ezpay.apiKey')
+ );
+ }
+
+ this.logger.log(`Using API key for department: ${department}`);
+ return apiKey;
+ }
+
+ /**
+ * Get all available departments and their API key status
+ */
+ getAvailableDepartments(): {
+ department: string;
+ hasApiKey: boolean;
+ }[] {
+ const departmentApiKeys =
+ this.configService.get('ezpay.departmentApiKeys') || {};
+
+ return Object.keys(departmentApiKeys).map((department) => ({
+ department,
+ hasApiKey: !!departmentApiKeys[department],
+ }));
+ }
+
+ /**
+ * Validate if a department has a configured API key
+ */
+ isDepartmentConfigured(department: string): boolean {
+ const departmentApiKeys = this.configService.get('ezpay.departmentApiKeys');
+ return !!(departmentApiKeys && departmentApiKeys[department]);
+ }
+}
diff --git a/src/payments/ezpay/ezpay.service.ts b/src/payments/ezpay/ezpay.service.ts
index ad85e3c..aa613e8 100644
--- a/src/payments/ezpay/ezpay.service.ts
+++ b/src/payments/ezpay/ezpay.service.ts
@@ -1,5 +1,6 @@
import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
+import { DepartmentMappingService } from '../department-mapping.service';
import {
CreatePaymentParams,
CreatePaymentResult,
@@ -23,13 +24,16 @@ import {
@Injectable()
export class EZPayService {
private readonly logger = new Logger(EZPayService.name);
- private readonly config: EZPayConfig;
+ private readonly defaultConfig: EZPayConfig;
- constructor(private configService: ConfigService) {
- this.config = this.getConfig();
+ constructor(
+ private configService: ConfigService,
+ private departmentMappingService: DepartmentMappingService,
+ ) {
+ this.defaultConfig = this.getDefaultConfig();
}
- private getConfig(): EZPayConfig {
+ private getDefaultConfig(): EZPayConfig {
const apiKey = this.configService.get('ezpay.apiKey');
const baseUrl = this.configService.get('ezpay.baseUrl');
@@ -43,6 +47,49 @@ export class EZPayService {
return { apiKey, baseUrl };
}
+ /**
+ * Get configuration with optional custom API key
+ */
+ private getConfigWithApiKey(customApiKey?: string): EZPayConfig {
+ if (customApiKey) {
+ return {
+ apiKey: customApiKey,
+ baseUrl: this.defaultConfig.baseUrl,
+ };
+ }
+ return this.defaultConfig;
+ }
+
+ /**
+ * Extract department from reference number
+ * Expected format: DEPARTMENT-formId-submissionId (e.g., EDUCATION-form123-sub456)
+ */
+ private extractDepartmentFromReference(reference: string): string | null {
+ // Check if reference follows the department format
+ const match = reference.match(/^([A-Z_]+)-(.+)-(.+)$/);
+ if (match) {
+ return match[1].toLowerCase(); // Convert EDUCATION to education
+ }
+
+ this.logger.warn(
+ `Reference ${reference} does not follow expected format DEPARTMENT-formId-submissionId. Using default API key.`,
+ );
+ return null;
+ }
+
+ /**
+ * Get API key for a reference number by extracting department
+ */
+ private getApiKeyForReference(reference: string): string {
+ const department = this.extractDepartmentFromReference(reference);
+ if (department) {
+ return this.departmentMappingService.getApiKeyForDepartment(department);
+ }
+
+ // Fallback to default API key
+ return this.departmentMappingService.getApiKeyForDepartment('default');
+ }
+
/**
* Generate a unique process ID (20 characters)
*/
@@ -53,8 +100,9 @@ export class EZPayService {
/**
* Get the payment page URL for a token
*/
- getPaymentPageUrl(token: string): string {
- return `${this.config.baseUrl}/payment_page?token=${token}`;
+ getPaymentPageUrl(token: string, customApiKey?: string): string {
+ const config = this.getConfigWithApiKey(customApiKey);
+ return `${config.baseUrl}/payment_page?token=${token}`;
}
/**
@@ -136,6 +184,7 @@ export class EZPayService {
*/
async createPayment(
params: CreatePaymentParams,
+ customApiKey?: string,
): Promise {
const {
cartItems,
@@ -148,6 +197,8 @@ export class EZPayService {
allowPayce = true,
} = params;
+ const config = this.getConfigWithApiKey(customApiKey);
+
try {
this.validateCartItems(cartItems);
@@ -165,11 +216,11 @@ export class EZPayService {
});
const response = await this.makeRequest(
- `${this.config.baseUrl}/ezpay_receivecart`,
+ `${config.baseUrl}/ezpay_receivecart`,
{
method: 'POST',
headers: {
- EZPluginKey: this.config.apiKey,
+ EZPluginKey: config.apiKey,
},
body: formData,
},
@@ -224,6 +275,7 @@ export class EZPayService {
*/
async verifyPayment(
params: VerifyPaymentParams,
+ customApiKey?: string,
): Promise {
if (!(params.transactionNumber || params.reference)) {
throw new EZPayValidationException(
@@ -231,6 +283,14 @@ export class EZPayService {
);
}
+ // Determine API key: use custom if provided, otherwise extract from reference
+ let apiKey = customApiKey;
+ if (!apiKey && params.reference) {
+ apiKey = this.getApiKeyForReference(params.reference);
+ }
+
+ const config = this.getConfigWithApiKey(apiKey);
+
try {
this.logger.log('Verifying payment', params);
@@ -243,11 +303,11 @@ export class EZPayService {
}
const response = await this.makeRequest(
- `${this.config.baseUrl}/check_api`,
+ `${config.baseUrl}/check_api`,
{
method: 'POST',
headers: {
- EZPluginKey: this.config.apiKey,
+ EZPluginKey: config.apiKey,
},
body: formData,
},
@@ -275,16 +335,19 @@ export class EZPayService {
async queryTransactions(
startDate: string,
endDate: string,
+ customApiKey?: string,
): Promise {
+ const config = this.getConfigWithApiKey(customApiKey);
+
try {
this.logger.log(`Querying transactions from ${startDate} to ${endDate}`);
const response = await this.makeRequest(
- `${this.config.baseUrl}/transactions_api`,
+ `${config.baseUrl}/transactions_api`,
{
method: 'POST',
headers: {
- Apikey: this.config.apiKey,
+ Apikey: config.apiKey,
Startdate: startDate,
Enddate: endDate,
},
diff --git a/src/payments/index.ts b/src/payments/index.ts
index 15f9154..077759f 100644
--- a/src/payments/index.ts
+++ b/src/payments/index.ts
@@ -1,3 +1,4 @@
export * from './payments.module';
export * from './payment-integration.service';
+export * from './department-mapping.service';
export * from './ezpay';
diff --git a/src/payments/payment-integration.service.ts b/src/payments/payment-integration.service.ts
index 84532b9..b2635c7 100644
--- a/src/payments/payment-integration.service.ts
+++ b/src/payments/payment-integration.service.ts
@@ -1,10 +1,12 @@
import { Injectable, Logger } from '@nestjs/common';
import { EZPayService } from './ezpay/ezpay.service';
+import { DepartmentMappingService } from './department-mapping.service';
import { EZPayCartItem, CreatePaymentResult } from './ezpay/interfaces';
export interface PaymentIntegrationOptions {
formId: string;
submissionId: string;
+ department: string; // Required department for API key selection
paymentCode: string;
amount: number;
description: string;
@@ -17,7 +19,10 @@ export interface PaymentIntegrationOptions {
export class PaymentIntegrationService {
private readonly logger = new Logger(PaymentIntegrationService.name);
- constructor(private readonly ezpayService: EZPayService) {}
+ constructor(
+ private readonly ezpayService: EZPayService,
+ private readonly departmentMappingService: DepartmentMappingService,
+ ) {}
/**
* Create a payment for a form submission
@@ -28,6 +33,7 @@ export class PaymentIntegrationService {
const {
formId,
submissionId,
+ department,
paymentCode,
amount,
description,
@@ -39,31 +45,48 @@ export class PaymentIntegrationService {
this.logger.log(`Creating payment for form submission`, {
formId,
submissionId,
+ department,
amount,
customerEmail,
});
+ // Get the correct API key for the department
+ const apiKey = department
+ ? this.departmentMappingService.getApiKeyForDepartment(department)
+ : this.departmentMappingService.getApiKeyForDepartment('default');
+
+ // Create reference number with department prefix - department is required
+ if (!department) {
+ throw new Error('Department is required for payment creation');
+ }
+
+ const referenceNumber =
+ reference || `${department.toUpperCase()}-${formId}-${submissionId}`;
+
// Create cart item for the form payment
const cartItems: EZPayCartItem[] = [
{
code: paymentCode,
amount,
details: description,
- reference: reference || `${formId}-${submissionId}`,
+ reference: referenceNumber,
},
];
try {
- const result = await this.ezpayService.createPayment({
- cartItems,
- customerEmail,
- customerName,
- referenceNumber: reference || `FORM-${formId}-${submissionId}`,
- processId: this.ezpayService.generateProcessId(),
- allowCredit: true,
- allowDebit: true,
- allowPayce: true,
- });
+ const result = await this.ezpayService.createPayment(
+ {
+ cartItems,
+ customerEmail,
+ customerName,
+ referenceNumber,
+ processId: this.ezpayService.generateProcessId(),
+ allowCredit: true,
+ allowDebit: true,
+ allowPayce: true,
+ },
+ apiKey,
+ );
if (result.success) {
this.logger.log(`Payment created for submission ${submissionId}`, {
@@ -109,6 +132,7 @@ export class PaymentIntegrationService {
});
try {
+ // EZPayService automatically determines the correct API key from the reference
const result = await this.ezpayService.verifyPayment({
transactionNumber,
reference,
@@ -120,9 +144,6 @@ export class PaymentIntegrationService {
amount: result.data._amount,
transactionNumber: result.data._transaction_number,
});
-
- // Here you could update the form submission status based on payment status
- // Example: update database record, send confirmation email, etc.
}
return result;
@@ -148,15 +169,26 @@ export class PaymentIntegrationService {
});
try {
- // Extract form ID and submission ID from reference if it follows the pattern
+ // Extract form ID and submission ID from reference
+ // Format: DEPARTMENT-formId-submissionId (e.g., EDUCATION-form123-sub456)
const referenceParts = callbackData._reference.split('-');
- if (referenceParts.length >= 3 && referenceParts[0] === 'FORM') {
+
+ if (referenceParts.length >= 3) {
+ const department = referenceParts[0].toLowerCase();
const formId = referenceParts[1];
const submissionId = referenceParts[2];
+ this.logger.log('Processing callback for department-based reference', {
+ department,
+ formId,
+ submissionId,
+ reference: callbackData._reference,
+ });
+
this.logger.log('Extracted form info from payment reference', {
formId,
submissionId,
+ department,
reference: callbackData._reference,
});
@@ -168,12 +200,16 @@ export class PaymentIntegrationService {
if (callbackData._status === 'Success') {
this.logger.log(
- `Payment successful for form ${formId}, submission ${submissionId}`,
+ `Payment successful for form ${formId}, submission ${submissionId}${
+ department ? ` (department: ${department})` : ''
+ }`,
);
// Handle successful payment
} else if (callbackData._status === 'Failed') {
this.logger.warn(
- `Payment failed for form ${formId}, submission ${submissionId}`,
+ `Payment failed for form ${formId}, submission ${submissionId}${
+ department ? ` (department: ${department})` : ''
+ }`,
);
// Handle failed payment
}
diff --git a/src/payments/payment-webhook.service.ts b/src/payments/payment-webhook.service.ts
index a908365..5c97a1b 100644
--- a/src/payments/payment-webhook.service.ts
+++ b/src/payments/payment-webhook.service.ts
@@ -439,15 +439,27 @@ export class PaymentWebhookService {
* Manually verify and synchronize payment status with EZPay
* This method can be used for manual verification or periodic reconciliation
*/
- async manualPaymentVerification(transactionNumber: string): Promise<{
+ async manualPaymentVerification(
+ transactionNumber?: string,
+ reference?: string,
+ ): Promise<{
success: boolean;
message: string;
data?: Payment;
}> {
try {
+ // Validate that both parameters are provided
+ if (!transactionNumber || !reference) {
+ return {
+ success: false,
+ message: 'Both transactionNumber and reference must be provided',
+ };
+ }
+
// Verify with EZPay
const verificationResult = await this.verifyPaymentStatus({
transactionNumber,
+ reference,
});
if (!verificationResult.success || !verificationResult.data) {
@@ -463,17 +475,32 @@ export class PaymentWebhookService {
);
// Find the payment in our database
- const payment = await this.paymentRepository.findOne({
- where: {
- referenceNumber: serializedDetails.reference,
- },
- relations: ['formSubmissions'],
- });
+ let payment: Payment | null = null;
+
+ if (serializedDetails?.reference) {
+ // Use reference from verified data if available
+ payment = await this.paymentRepository.findOne({
+ where: {
+ referenceNumber: serializedDetails.reference,
+ },
+ relations: ['formSubmissions'],
+ });
+ } else if (reference) {
+ // Use provided reference parameter
+ payment = await this.paymentRepository.findOne({
+ where: {
+ referenceNumber: reference,
+ },
+ relations: ['formSubmissions'],
+ });
+ }
if (!payment) {
+ const usedReference =
+ serializedDetails?.reference || reference || 'unknown';
return {
success: false,
- message: `Payment not found for reference: ${serializedDetails.reference}`,
+ message: `Payment not found for reference: ${usedReference}`,
};
}
@@ -495,7 +522,7 @@ export class PaymentWebhookService {
// Create/update transaction record
const callbackData: EZPayCallbackDto = {
- _reference: serializedDetails.reference,
+ _reference: serializedDetails?.reference || reference || '',
_status: paymentData._status as any,
_transaction_number: paymentData._transaction_number,
_ezpay_account: paymentData._ezpay_account,
@@ -511,7 +538,7 @@ export class PaymentWebhookService {
`Payment status updated from ${currentStatus} to ${verifiedStatus}`,
{
paymentId: payment.id,
- referenceNumber: serializedDetails.reference,
+ referenceNumber: serializedDetails?.reference || reference,
transactionNumber: paymentData._transaction_number,
},
);
@@ -542,6 +569,8 @@ export class PaymentWebhookService {
this.logger.error('Manual payment verification failed', {
error: error.message,
stack: error.stack,
+ transactionNumber,
+ reference,
});
return {
diff --git a/src/payments/payment.controller.ts b/src/payments/payment.controller.ts
index 460d1a3..209df73 100644
--- a/src/payments/payment.controller.ts
+++ b/src/payments/payment.controller.ts
@@ -8,6 +8,7 @@ import {
Logger,
Param,
Post,
+ Query,
Req,
} from '@nestjs/common';
import { Request } from 'express';
@@ -100,6 +101,25 @@ export class PaymentsController {
data?: any;
}> {
const result = await this.paymentWebhookService.manualPaymentVerification(
+ undefined,
+ reference,
+ );
+
+ return result;
+ }
+
+ @Get('verify')
+ @HttpCode(HttpStatus.OK)
+ async verifyPayment(
+ @Query('transactionNumber') transactionNumber?: string,
+ @Query('reference') reference?: string,
+ ): Promise<{
+ success: boolean;
+ message: string;
+ data?: any;
+ }> {
+ const result = await this.paymentWebhookService.manualPaymentVerification(
+ transactionNumber,
reference,
);
diff --git a/src/payments/payments.module.ts b/src/payments/payments.module.ts
index 6146bec..c5e48a3 100644
--- a/src/payments/payments.module.ts
+++ b/src/payments/payments.module.ts
@@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { PaymentIntegrationService } from './payment-integration.service';
import { PaymentWebhookService } from './payment-webhook.service';
+import { DepartmentMappingService } from './department-mapping.service';
import {
Payment,
PaymentTransaction,
@@ -17,8 +18,17 @@ import { EZPayService, PaymentsController } from './ezpay';
FormSubmissionPayment,
]),
],
- providers: [PaymentIntegrationService, PaymentWebhookService, EZPayService],
+ providers: [
+ PaymentIntegrationService,
+ PaymentWebhookService,
+ EZPayService,
+ DepartmentMappingService,
+ ],
controllers: [PaymentsController],
- exports: [PaymentIntegrationService, PaymentWebhookService],
+ exports: [
+ PaymentIntegrationService,
+ PaymentWebhookService,
+ DepartmentMappingService,
+ ],
})
export class PaymentsModule {}
diff --git a/src/processors/implementations/payment.processor.ts b/src/processors/implementations/payment.processor.ts
index bed3e45..2fee8dd 100644
--- a/src/processors/implementations/payment.processor.ts
+++ b/src/processors/implementations/payment.processor.ts
@@ -1,15 +1,18 @@
import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
-import { ConfigService } from '@nestjs/config';
import { EZPayService } from '../../payments/ezpay/ezpay.service';
+import { DepartmentMappingService } from '../../payments/department-mapping.service';
import {
Payment,
PaymentStatus,
PaymentProvider,
FormSubmissionPayment,
} from '../../database/entities';
-import { PaymentProcessorConfig } from '../../forms/interfaces/form-schema.interface';
+import {
+ PaymentProcessorConfig,
+ ResponseDataConfig,
+} from '../../forms/interfaces/form-schema.interface';
import { IProcessor } from '../interfaces/processor.interface';
export interface PaymentProcessorResult {
@@ -22,6 +25,7 @@ export interface PaymentProcessorResult {
amount?: number;
description?: string;
error?: string;
+ additionalData?: Record;
}
@Injectable()
@@ -34,7 +38,7 @@ export class PaymentProcessor implements IProcessor {
@InjectRepository(FormSubmissionPayment)
private formSubmissionPaymentRepository: Repository,
private ezpayService: EZPayService,
- private configService: ConfigService,
+ private departmentMappingService: DepartmentMappingService,
) {}
get type(): string {
@@ -49,7 +53,7 @@ export class PaymentProcessor implements IProcessor {
data: Record;
},
): Promise {
- const result = await this.process(config, config, context);
+ const result = await this.process(context.data, config, context);
if (!result.success) {
throw new Error(result.error || 'Payment processing failed');
}
@@ -71,7 +75,7 @@ export class PaymentProcessor implements IProcessor {
});
// Resolve configuration values
- const resolvedConfig = await this.resolveConfig(config, formData);
+ const resolvedConfig = await this.resolveConfig(config);
// Validate payment configuration
if (!resolvedConfig.paymentCode) {
@@ -95,23 +99,26 @@ export class PaymentProcessor implements IProcessor {
});
// Create EZPay payment session
- const ezpayResult = await this.ezpayService.createPayment({
- cartItems: [
- {
- code: resolvedConfig.paymentCode,
- amount: resolvedConfig.amount,
- details: resolvedConfig.description,
- reference: payment.referenceNumber,
- },
- ],
- customerEmail: customerInfo.email,
- customerName: customerInfo.name,
- referenceNumber: payment.referenceNumber,
- processId: payment.processId,
- allowCredit: resolvedConfig.allowCredit ?? true,
- allowDebit: resolvedConfig.allowDebit ?? true,
- allowPayce: resolvedConfig.allowPayce ?? true,
- });
+ const ezpayResult = await this.ezpayService.createPayment(
+ {
+ cartItems: [
+ {
+ code: resolvedConfig.paymentCode,
+ amount: resolvedConfig.amount,
+ details: resolvedConfig.description,
+ reference: payment.referenceNumber,
+ },
+ ],
+ customerEmail: customerInfo.email,
+ customerName: customerInfo.name,
+ referenceNumber: payment.referenceNumber,
+ processId: payment.processId,
+ allowCredit: resolvedConfig.allowCredit ?? true,
+ allowDebit: resolvedConfig.allowDebit ?? true,
+ allowPayce: resolvedConfig.allowPayce ?? true,
+ },
+ resolvedConfig.apiKey,
+ );
if (!ezpayResult.success) {
// Update payment status to failed
@@ -162,6 +169,11 @@ export class PaymentProcessor implements IProcessor {
},
);
+ // Process additional response data if configured
+ const additionalData = config.responseData
+ ? await this.processResponseData(config.responseData, formData)
+ : undefined;
+
return {
success: true,
paymentRequired: true,
@@ -171,6 +183,7 @@ export class PaymentProcessor implements IProcessor {
referenceNumber: payment.referenceNumber,
amount: resolvedConfig.amount,
description: resolvedConfig.description,
+ additionalData,
};
} catch (error) {
this.logger.error(
@@ -188,75 +201,44 @@ export class PaymentProcessor implements IProcessor {
private async resolveConfig(
config: PaymentProcessorConfig['config'],
- formData: Record,
): Promise<{
+ department: string;
paymentCode: string;
amount: number;
description: string;
allowCredit: boolean;
allowDebit: boolean;
allowPayce: boolean;
+ apiKey: string;
}> {
- // Resolve payment code from database secrets
- let paymentCode = config.paymentCode;
- if (paymentCode.startsWith('{{db:')) {
- paymentCode = await this.resolveDbSecret(paymentCode);
- }
+ // At this point, all expressions should already be resolved by FormUtilsService
+ const paymentCode = config.paymentCode;
+ const amount = Number(config.amount) || 0;
- // Resolve amount (could be dynamic based on form data)
- let amount = config.amount;
- if (typeof amount === 'string') {
- amount = this.evaluateAmountFormula(amount, formData);
- }
+ // Get the department and corresponding API key
+ const department = config.department || 'default';
+ const apiKey =
+ this.departmentMappingService.getApiKeyForDepartment(department);
+
+ this.logger.log(`Resolved payment config:`, {
+ department,
+ paymentCode,
+ amount,
+ description: config.description,
+ });
return {
+ department,
paymentCode,
- amount: Number(amount),
+ amount,
description: config.description,
allowCredit: config.allowCredit ?? true,
allowDebit: config.allowDebit ?? true,
allowPayce: config.allowPayce ?? true,
+ apiKey,
};
}
- private async resolveDbSecret(secretRef: string): Promise {
- // Extract secret path from {{db:form-id:secret-key}} format
- const match = secretRef.match(/\{\{db:([^:]+):([^}]+)\}\}/);
- if (!match) {
- throw new Error(`Invalid secret reference format: ${secretRef}`);
- }
-
- const [, formId, secretKey] = match;
-
- // This would typically query your form config or secrets table
- // For now, using environment variables as fallback
- const envKey = `${formId
- .toUpperCase()
- .replace(/-/g, '_')}_${secretKey.toUpperCase()}`;
- const value = this.configService.get(envKey);
-
- if (!value) {
- throw new Error(`Secret not found: ${secretRef} (tried ${envKey})`);
- }
-
- return value;
- }
-
- private evaluateAmountFormula(
- formula: string,
- formData: Record,
- ): number {
- // Simple formula evaluation (could be extended with a proper expression parser)
- if (formula.startsWith('{{formData.') && formula.endsWith('}}')) {
- const path = formula.slice(12, -2); // Remove {{formData. and }}
- const value = this.getNestedValue(formData, path);
- return Number(value) || 0;
- }
-
- // If it's just a number as string
- return Number(formula) || 0;
- }
-
private getNestedValue(obj: any, path: string): any {
return path.split('.').reduce((current, key) => current?.[key], obj);
}
@@ -287,6 +269,7 @@ export class PaymentProcessor implements IProcessor {
}
private async createPaymentRecord(data: {
+ department: string;
paymentCode: string;
amount: number;
description: string;
@@ -295,8 +278,13 @@ export class PaymentProcessor implements IProcessor {
formId: string;
submissionId: string;
}): Promise {
+ // Include department in reference number for later API key resolution
+ const referenceNumber = `${data.department.toUpperCase()}-${data.formId}-${
+ data.submissionId
+ }`;
+
const payment = this.paymentRepository.create({
- referenceNumber: `${data.formId}-${data.submissionId}`,
+ referenceNumber,
processId: this.ezpayService.generateProcessId(),
paymentProvider: PaymentProvider.EZPAY,
totalAmount: data.amount,
@@ -398,4 +386,28 @@ export class PaymentProcessor implements IProcessor {
payment: formSubmissionPayment.payment,
};
}
+
+ /**
+ * Process response data configuration to extract additional data from form data
+ */
+ private async processResponseData(
+ responseConfig: ResponseDataConfig,
+ formData: Record,
+ ): Promise> {
+ const result: Record = {};
+
+ // Include specified form fields
+ if (responseConfig.include) {
+ for (const fieldPath of responseConfig.include) {
+ const value = this.getNestedValue(formData, fieldPath);
+ if (value !== undefined) {
+ // Use the last part of the field path as the key (e.g., order.numberOfCopies -> numberOfCopies)
+ const fieldName = fieldPath.split('.').pop() || fieldPath;
+ result[fieldName] = value;
+ }
+ }
+ }
+
+ return result;
+ }
}
diff --git a/src/processors/processors.module.ts b/src/processors/processors.module.ts
index aeade56..9e98dbe 100644
--- a/src/processors/processors.module.ts
+++ b/src/processors/processors.module.ts
@@ -6,7 +6,7 @@ import { PaymentsModule } from '../payments/payments.module';
import { Payment, FormSubmissionPayment } from '../database/entities';
import { EmailProcessor } from './implementations/email.processor';
import { PaymentProcessor } from './implementations/payment.processor';
-import { EZPayService } from '../payments';
+import { EZPayService, DepartmentMappingService } from '../payments';
@Module({
imports: [
@@ -19,6 +19,7 @@ import { EZPayService } from '../payments';
EmailProcessor,
PaymentProcessor,
EZPayService,
+ DepartmentMappingService,
],
exports: [ProcessorPipelineService],
})