summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/package-lock.json1621
-rw-r--r--app/package.json1
-rw-r--r--app/src/app.d.ts3
-rw-r--r--app/src/hooks.server.ts26
-rw-r--r--app/src/lib/common/assignments.ts32
-rw-r--r--app/src/lib/server/assignments.ts106
-rw-r--r--app/src/lib/server/s3.ts16
-rw-r--r--app/src/lib/server/sessions.ts4
-rw-r--r--app/src/routes/assignments/[assignmentId]/+page.server.ts30
-rw-r--r--app/src/routes/assignments/[assignmentId]/+page.svelte30
-rw-r--r--db/dump.sql250
11 files changed, 2083 insertions, 36 deletions
diff --git a/app/package-lock.json b/app/package-lock.json
index a69ae8d..1614662 100644
--- a/app/package-lock.json
+++ b/app/package-lock.json
@@ -8,6 +8,7 @@
"name": "app",
"version": "0.0.1",
"dependencies": {
+ "@aws-sdk/client-s3": "^3.750.0",
"pg": "^8.13.3"
},
"devDependencies": {
@@ -44,6 +45,856 @@
"node": ">=6.0.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==",
+ "license": "Apache-2.0",
+ "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/crc32c": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz",
+ "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "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==",
+ "license": "Apache-2.0",
+ "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==",
+ "license": "Apache-2.0",
+ "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==",
+ "license": "Apache-2.0",
+ "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==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "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",
+ "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-js": "^5.2.0",
+ "@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/sha256-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==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-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==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-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==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-js": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz",
+ "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==",
+ "license": "Apache-2.0",
+ "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/supports-web-crypto": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz",
+ "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-crypto/util": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz",
+ "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.222.0",
+ "@smithy/util-utf8": "^2.0.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-crypto/util/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==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/util/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==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/util/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==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3": {
+ "version": "3.750.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.750.0.tgz",
+ "integrity": "sha512-S9G9noCeBxchoMVkHYrRi1A1xW/VOTP2W7X34lP+Y7Wpl32yMA7IJo0fAGAuTc0q1Nu6/pXDm+oDG7rhTCA1tg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha1-browser": "5.2.0",
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "3.750.0",
+ "@aws-sdk/credential-provider-node": "3.750.0",
+ "@aws-sdk/middleware-bucket-endpoint": "3.734.0",
+ "@aws-sdk/middleware-expect-continue": "3.734.0",
+ "@aws-sdk/middleware-flexible-checksums": "3.750.0",
+ "@aws-sdk/middleware-host-header": "3.734.0",
+ "@aws-sdk/middleware-location-constraint": "3.734.0",
+ "@aws-sdk/middleware-logger": "3.734.0",
+ "@aws-sdk/middleware-recursion-detection": "3.734.0",
+ "@aws-sdk/middleware-sdk-s3": "3.750.0",
+ "@aws-sdk/middleware-ssec": "3.734.0",
+ "@aws-sdk/middleware-user-agent": "3.750.0",
+ "@aws-sdk/region-config-resolver": "3.734.0",
+ "@aws-sdk/signature-v4-multi-region": "3.750.0",
+ "@aws-sdk/types": "3.734.0",
+ "@aws-sdk/util-endpoints": "3.743.0",
+ "@aws-sdk/util-user-agent-browser": "3.734.0",
+ "@aws-sdk/util-user-agent-node": "3.750.0",
+ "@aws-sdk/xml-builder": "3.734.0",
+ "@smithy/config-resolver": "^4.0.1",
+ "@smithy/core": "^3.1.4",
+ "@smithy/eventstream-serde-browser": "^4.0.1",
+ "@smithy/eventstream-serde-config-resolver": "^4.0.1",
+ "@smithy/eventstream-serde-node": "^4.0.1",
+ "@smithy/fetch-http-handler": "^5.0.1",
+ "@smithy/hash-blob-browser": "^4.0.1",
+ "@smithy/hash-node": "^4.0.1",
+ "@smithy/hash-stream-node": "^4.0.1",
+ "@smithy/invalid-dependency": "^4.0.1",
+ "@smithy/md5-js": "^4.0.1",
+ "@smithy/middleware-content-length": "^4.0.1",
+ "@smithy/middleware-endpoint": "^4.0.5",
+ "@smithy/middleware-retry": "^4.0.6",
+ "@smithy/middleware-serde": "^4.0.2",
+ "@smithy/middleware-stack": "^4.0.1",
+ "@smithy/node-config-provider": "^4.0.1",
+ "@smithy/node-http-handler": "^4.0.2",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/smithy-client": "^4.1.5",
+ "@smithy/types": "^4.1.0",
+ "@smithy/url-parser": "^4.0.1",
+ "@smithy/util-base64": "^4.0.0",
+ "@smithy/util-body-length-browser": "^4.0.0",
+ "@smithy/util-body-length-node": "^4.0.0",
+ "@smithy/util-defaults-mode-browser": "^4.0.6",
+ "@smithy/util-defaults-mode-node": "^4.0.6",
+ "@smithy/util-endpoints": "^3.0.1",
+ "@smithy/util-middleware": "^4.0.1",
+ "@smithy/util-retry": "^4.0.1",
+ "@smithy/util-stream": "^4.1.1",
+ "@smithy/util-utf8": "^4.0.0",
+ "@smithy/util-waiter": "^4.0.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-sso": {
+ "version": "3.750.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.750.0.tgz",
+ "integrity": "sha512-y0Rx6pTQXw0E61CaptpZF65qNggjqOgymq/RYZU5vWba5DGQ+iqGt8Yq8s+jfBoBBNXshxq8l8Dl5Uq/JTY1wg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "3.750.0",
+ "@aws-sdk/middleware-host-header": "3.734.0",
+ "@aws-sdk/middleware-logger": "3.734.0",
+ "@aws-sdk/middleware-recursion-detection": "3.734.0",
+ "@aws-sdk/middleware-user-agent": "3.750.0",
+ "@aws-sdk/region-config-resolver": "3.734.0",
+ "@aws-sdk/types": "3.734.0",
+ "@aws-sdk/util-endpoints": "3.743.0",
+ "@aws-sdk/util-user-agent-browser": "3.734.0",
+ "@aws-sdk/util-user-agent-node": "3.750.0",
+ "@smithy/config-resolver": "^4.0.1",
+ "@smithy/core": "^3.1.4",
+ "@smithy/fetch-http-handler": "^5.0.1",
+ "@smithy/hash-node": "^4.0.1",
+ "@smithy/invalid-dependency": "^4.0.1",
+ "@smithy/middleware-content-length": "^4.0.1",
+ "@smithy/middleware-endpoint": "^4.0.5",
+ "@smithy/middleware-retry": "^4.0.6",
+ "@smithy/middleware-serde": "^4.0.2",
+ "@smithy/middleware-stack": "^4.0.1",
+ "@smithy/node-config-provider": "^4.0.1",
+ "@smithy/node-http-handler": "^4.0.2",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/smithy-client": "^4.1.5",
+ "@smithy/types": "^4.1.0",
+ "@smithy/url-parser": "^4.0.1",
+ "@smithy/util-base64": "^4.0.0",
+ "@smithy/util-body-length-browser": "^4.0.0",
+ "@smithy/util-body-length-node": "^4.0.0",
+ "@smithy/util-defaults-mode-browser": "^4.0.6",
+ "@smithy/util-defaults-mode-node": "^4.0.6",
+ "@smithy/util-endpoints": "^3.0.1",
+ "@smithy/util-middleware": "^4.0.1",
+ "@smithy/util-retry": "^4.0.1",
+ "@smithy/util-utf8": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/core": {
+ "version": "3.750.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.750.0.tgz",
+ "integrity": "sha512-bZ5K7N5L4+Pa2epbVpUQqd1XLG2uU8BGs/Sd+2nbgTf+lNQJyIxAg/Qsrjz9MzmY8zzQIeRQEkNmR6yVAfCmmQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/core": "^3.1.4",
+ "@smithy/node-config-provider": "^4.0.1",
+ "@smithy/property-provider": "^4.0.1",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/signature-v4": "^5.0.1",
+ "@smithy/smithy-client": "^4.1.5",
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-middleware": "^4.0.1",
+ "fast-xml-parser": "4.4.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-env": {
+ "version": "3.750.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.750.0.tgz",
+ "integrity": "sha512-In6bsG0p/P31HcH4DBRKBbcDS/3SHvEPjfXV8ODPWZO/l3/p7IRoYBdQ07C9R+VMZU2D0+/Sc/DWK/TUNDk1+Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.750.0",
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/property-provider": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-http": {
+ "version": "3.750.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.750.0.tgz",
+ "integrity": "sha512-wFB9qqfa20AB0dElsQz5ZlZT5o+a+XzpEpmg0erylmGYqEOvh8NQWfDUVpRmQuGq9VbvW/8cIbxPoNqEbPtuWQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.750.0",
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/fetch-http-handler": "^5.0.1",
+ "@smithy/node-http-handler": "^4.0.2",
+ "@smithy/property-provider": "^4.0.1",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/smithy-client": "^4.1.5",
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-stream": "^4.1.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-ini": {
+ "version": "3.750.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.750.0.tgz",
+ "integrity": "sha512-2YIZmyEr5RUd3uxXpxOLD9G67Bibm4I/65M6vKFP17jVMUT+R1nL7mKqmhEVO2p+BoeV+bwMyJ/jpTYG368PCg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.750.0",
+ "@aws-sdk/credential-provider-env": "3.750.0",
+ "@aws-sdk/credential-provider-http": "3.750.0",
+ "@aws-sdk/credential-provider-process": "3.750.0",
+ "@aws-sdk/credential-provider-sso": "3.750.0",
+ "@aws-sdk/credential-provider-web-identity": "3.750.0",
+ "@aws-sdk/nested-clients": "3.750.0",
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/credential-provider-imds": "^4.0.1",
+ "@smithy/property-provider": "^4.0.1",
+ "@smithy/shared-ini-file-loader": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-node": {
+ "version": "3.750.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.750.0.tgz",
+ "integrity": "sha512-THWHHAceLwsOiowPEmKyhWVDlEUxH07GHSw5AQFDvNQtGKOQl0HSIFO1mKObT2Q2Vqzji9Bq8H58SO5BFtNPRw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/credential-provider-env": "3.750.0",
+ "@aws-sdk/credential-provider-http": "3.750.0",
+ "@aws-sdk/credential-provider-ini": "3.750.0",
+ "@aws-sdk/credential-provider-process": "3.750.0",
+ "@aws-sdk/credential-provider-sso": "3.750.0",
+ "@aws-sdk/credential-provider-web-identity": "3.750.0",
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/credential-provider-imds": "^4.0.1",
+ "@smithy/property-provider": "^4.0.1",
+ "@smithy/shared-ini-file-loader": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-process": {
+ "version": "3.750.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.750.0.tgz",
+ "integrity": "sha512-Q78SCH1n0m7tpu36sJwfrUSxI8l611OyysjQeMiIOliVfZICEoHcLHLcLkiR+tnIpZ3rk7d2EQ6R1jwlXnalMQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.750.0",
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/property-provider": "^4.0.1",
+ "@smithy/shared-ini-file-loader": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-sso": {
+ "version": "3.750.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.750.0.tgz",
+ "integrity": "sha512-FGYrDjXN/FOQVi/t8fHSv8zCk+NEvtFnuc4cZUj5OIbM4vrfFc5VaPyn41Uza3iv6Qq9rZg0QOwWnqK8lNrqUw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/client-sso": "3.750.0",
+ "@aws-sdk/core": "3.750.0",
+ "@aws-sdk/token-providers": "3.750.0",
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/property-provider": "^4.0.1",
+ "@smithy/shared-ini-file-loader": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-web-identity": {
+ "version": "3.750.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.750.0.tgz",
+ "integrity": "sha512-Nz8zs3YJ+GOTSrq+LyzbbC1Ffpt7pK38gcOyNZv76pP5MswKTUKNYBJehqwa+i7FcFQHsCk3TdhR8MT1ZR23uA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.750.0",
+ "@aws-sdk/nested-clients": "3.750.0",
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/property-provider": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-bucket-endpoint": {
+ "version": "3.734.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.734.0.tgz",
+ "integrity": "sha512-etC7G18aF7KdZguW27GE/wpbrNmYLVT755EsFc8kXpZj8D6AFKxc7OuveinJmiy0bYXAMspJUWsF6CrGpOw6CQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.734.0",
+ "@aws-sdk/util-arn-parser": "3.723.0",
+ "@smithy/node-config-provider": "^4.0.1",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-config-provider": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-expect-continue": {
+ "version": "3.734.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.734.0.tgz",
+ "integrity": "sha512-P38/v1l6HjuB2aFUewt7ueAW5IvKkFcv5dalPtbMGRhLeyivBOHwbCyuRKgVs7z7ClTpu9EaViEGki2jEQqEsQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-flexible-checksums": {
+ "version": "3.750.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.750.0.tgz",
+ "integrity": "sha512-ach0d2buDnX2TUausUbiXXFWFo3IegLnCrA+Rw8I9AYVpLN9lTaRwAYJwYC6zEuW9Golff8MwkYsp/OaC5tKMw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/crc32": "5.2.0",
+ "@aws-crypto/crc32c": "5.2.0",
+ "@aws-crypto/util": "5.2.0",
+ "@aws-sdk/core": "3.750.0",
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/is-array-buffer": "^4.0.0",
+ "@smithy/node-config-provider": "^4.0.1",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-middleware": "^4.0.1",
+ "@smithy/util-stream": "^4.1.1",
+ "@smithy/util-utf8": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-host-header": {
+ "version": "3.734.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.734.0.tgz",
+ "integrity": "sha512-LW7RRgSOHHBzWZnigNsDIzu3AiwtjeI2X66v+Wn1P1u+eXssy1+up4ZY/h+t2sU4LU36UvEf+jrZti9c6vRnFw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-location-constraint": {
+ "version": "3.734.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.734.0.tgz",
+ "integrity": "sha512-EJEIXwCQhto/cBfHdm3ZOeLxd2NlJD+X2F+ZTOxzokuhBtY0IONfC/91hOo5tWQweerojwshSMHRCKzRv1tlwg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-logger": {
+ "version": "3.734.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.734.0.tgz",
+ "integrity": "sha512-mUMFITpJUW3LcKvFok176eI5zXAUomVtahb9IQBwLzkqFYOrMJvWAvoV4yuxrJ8TlQBG8gyEnkb9SnhZvjg67w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-recursion-detection": {
+ "version": "3.734.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.734.0.tgz",
+ "integrity": "sha512-CUat2d9ITsFc2XsmeiRQO96iWpxSKYFjxvj27Hc7vo87YUHRnfMfnc8jw1EpxEwMcvBD7LsRa6vDNky6AjcrFA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-sdk-s3": {
+ "version": "3.750.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.750.0.tgz",
+ "integrity": "sha512-3H6Z46cmAQCHQ0z8mm7/cftY5ifiLfCjbObrbyyp2fhQs9zk6gCKzIX8Zjhw0RMd93FZi3ebRuKJWmMglf4Itw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.750.0",
+ "@aws-sdk/types": "3.734.0",
+ "@aws-sdk/util-arn-parser": "3.723.0",
+ "@smithy/core": "^3.1.4",
+ "@smithy/node-config-provider": "^4.0.1",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/signature-v4": "^5.0.1",
+ "@smithy/smithy-client": "^4.1.5",
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-config-provider": "^4.0.0",
+ "@smithy/util-middleware": "^4.0.1",
+ "@smithy/util-stream": "^4.1.1",
+ "@smithy/util-utf8": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-ssec": {
+ "version": "3.734.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.734.0.tgz",
+ "integrity": "sha512-d4yd1RrPW/sspEXizq2NSOUivnheac6LPeLSLnaeTbBG9g1KqIqvCzP1TfXEqv2CrWfHEsWtJpX7oyjySSPvDQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-user-agent": {
+ "version": "3.750.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.750.0.tgz",
+ "integrity": "sha512-YYcslDsP5+2NZoN3UwuhZGkhAHPSli7HlJHBafBrvjGV/I9f8FuOO1d1ebxGdEP4HyRXUGyh+7Ur4q+Psk0ryw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.750.0",
+ "@aws-sdk/types": "3.734.0",
+ "@aws-sdk/util-endpoints": "3.743.0",
+ "@smithy/core": "^3.1.4",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/nested-clients": {
+ "version": "3.750.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.750.0.tgz",
+ "integrity": "sha512-OH68BRF0rt9nDloq4zsfeHI0G21lj11a66qosaljtEP66PWm7tQ06feKbFkXHT5E1K3QhJW3nVyK8v2fEBY5fg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "3.750.0",
+ "@aws-sdk/middleware-host-header": "3.734.0",
+ "@aws-sdk/middleware-logger": "3.734.0",
+ "@aws-sdk/middleware-recursion-detection": "3.734.0",
+ "@aws-sdk/middleware-user-agent": "3.750.0",
+ "@aws-sdk/region-config-resolver": "3.734.0",
+ "@aws-sdk/types": "3.734.0",
+ "@aws-sdk/util-endpoints": "3.743.0",
+ "@aws-sdk/util-user-agent-browser": "3.734.0",
+ "@aws-sdk/util-user-agent-node": "3.750.0",
+ "@smithy/config-resolver": "^4.0.1",
+ "@smithy/core": "^3.1.4",
+ "@smithy/fetch-http-handler": "^5.0.1",
+ "@smithy/hash-node": "^4.0.1",
+ "@smithy/invalid-dependency": "^4.0.1",
+ "@smithy/middleware-content-length": "^4.0.1",
+ "@smithy/middleware-endpoint": "^4.0.5",
+ "@smithy/middleware-retry": "^4.0.6",
+ "@smithy/middleware-serde": "^4.0.2",
+ "@smithy/middleware-stack": "^4.0.1",
+ "@smithy/node-config-provider": "^4.0.1",
+ "@smithy/node-http-handler": "^4.0.2",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/smithy-client": "^4.1.5",
+ "@smithy/types": "^4.1.0",
+ "@smithy/url-parser": "^4.0.1",
+ "@smithy/util-base64": "^4.0.0",
+ "@smithy/util-body-length-browser": "^4.0.0",
+ "@smithy/util-body-length-node": "^4.0.0",
+ "@smithy/util-defaults-mode-browser": "^4.0.6",
+ "@smithy/util-defaults-mode-node": "^4.0.6",
+ "@smithy/util-endpoints": "^3.0.1",
+ "@smithy/util-middleware": "^4.0.1",
+ "@smithy/util-retry": "^4.0.1",
+ "@smithy/util-utf8": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/region-config-resolver": {
+ "version": "3.734.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.734.0.tgz",
+ "integrity": "sha512-Lvj1kPRC5IuJBr9DyJ9T9/plkh+EfKLy+12s/mykOy1JaKHDpvj+XGy2YO6YgYVOb8JFtaqloid+5COtje4JTQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/node-config-provider": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-config-provider": "^4.0.0",
+ "@smithy/util-middleware": "^4.0.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/signature-v4-multi-region": {
+ "version": "3.750.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.750.0.tgz",
+ "integrity": "sha512-RA9hv1Irro/CrdPcOEXKwJ0DJYJwYCsauGEdRXihrRfy8MNSR9E+mD5/Fr5Rxjaq5AHM05DYnN3mg/DU6VwzSw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/middleware-sdk-s3": "3.750.0",
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/signature-v4": "^5.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/token-providers": {
+ "version": "3.750.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.750.0.tgz",
+ "integrity": "sha512-X/KzqZw41iWolwNdc8e3RMcNSMR364viHv78u6AefXOO5eRM40c4/LuST1jDzq35/LpnqRhL7/MuixOetw+sFw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/nested-clients": "3.750.0",
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/property-provider": "^4.0.1",
+ "@smithy/shared-ini-file-loader": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/types": {
+ "version": "3.734.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.734.0.tgz",
+ "integrity": "sha512-o11tSPTT70nAkGV1fN9wm/hAIiLPyWX6SuGf+9JyTp7S/rC2cFWhR26MvA69nplcjNaXVzB0f+QFrLXXjOqCrg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-arn-parser": {
+ "version": "3.723.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.723.0.tgz",
+ "integrity": "sha512-ZhEfvUwNliOQROcAk34WJWVYTlTa4694kSVhDSjW6lE1bMataPnIN8A0ycukEzBXmd8ZSoBcQLn6lKGl7XIJ5w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-endpoints": {
+ "version": "3.743.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.743.0.tgz",
+ "integrity": "sha512-sN1l559zrixeh5x+pttrnd0A3+r34r0tmPkJ/eaaMaAzXqsmKU/xYre9K3FNnsSS1J1k4PEfk/nHDTVUgFYjnw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-endpoints": "^3.0.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-locate-window": {
+ "version": "3.723.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.723.0.tgz",
+ "integrity": "sha512-Yf2CS10BqK688DRsrKI/EO6B8ff5J86NXe4C+VCysK7UOgN0l1zOTeTukZ3H8Q9tYYX3oaF1961o8vRkFm7Nmw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-user-agent-browser": {
+ "version": "3.734.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.734.0.tgz",
+ "integrity": "sha512-xQTCus6Q9LwUuALW+S76OL0jcWtMOVu14q+GoLnWPUM7QeUw963oQcLhF7oq0CtaLLKyl4GOUfcwc773Zmwwng==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/types": "^4.1.0",
+ "bowser": "^2.11.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-sdk/util-user-agent-node": {
+ "version": "3.750.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.750.0.tgz",
+ "integrity": "sha512-84HJj9G9zbrHX2opLk9eHfDceB+UIHVrmflMzWHpsmo9fDuro/flIBqaVDlE021Osj6qIM0SJJcnL6s23j7JEw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/middleware-user-agent": "3.750.0",
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/node-config-provider": "^4.0.1",
+ "@smithy/types": "^4.1.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/xml-builder": {
+ "version": "3.734.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.734.0.tgz",
+ "integrity": "sha512-Zrjxi5qwGEcUsJ0ru7fRtW74WcTS0rbLcehoFB+rN1GRi2hbLcFaYs4PwVA5diLeAJH0gszv3x4Hr/S87MfbKQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
"node_modules/@esbuild/aix-ppc64": {
"version": "0.24.2",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz",
@@ -1071,6 +1922,723 @@
"win32"
]
},
+ "node_modules/@smithy/abort-controller": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.1.tgz",
+ "integrity": "sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/chunked-blob-reader": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.0.0.tgz",
+ "integrity": "sha512-+sKqDBQqb036hh4NPaUiEkYFkTUGYzRsn3EuFhyfQfMy6oGHEUJDurLP9Ufb5dasr/XiAmPNMr6wa9afjQB+Gw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/chunked-blob-reader-native": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.0.0.tgz",
+ "integrity": "sha512-R9wM2yPmfEMsUmlMlIgSzOyICs0x9uu7UTHoccMyt7BWw8shcGM8HqB355+BZCPBcySvbTYMs62EgEQkNxz2ig==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-base64": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/config-resolver": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.0.1.tgz",
+ "integrity": "sha512-Igfg8lKu3dRVkTSEm98QpZUvKEOa71jDX4vKRcvJVyRc3UgN3j7vFMf0s7xLQhYmKa8kyJGQgUJDOV5V3neVlQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/node-config-provider": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-config-provider": "^4.0.0",
+ "@smithy/util-middleware": "^4.0.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/core": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.1.4.tgz",
+ "integrity": "sha512-wFExFGK+7r2wYriOqe7RRIBNpvxwiS95ih09+GSLRBdoyK/O1uZA7K7pKesj5CBvwJuSBeXwLyR88WwIAY+DGA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/middleware-serde": "^4.0.2",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-body-length-browser": "^4.0.0",
+ "@smithy/util-middleware": "^4.0.1",
+ "@smithy/util-stream": "^4.1.1",
+ "@smithy/util-utf8": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/credential-provider-imds": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.1.tgz",
+ "integrity": "sha512-l/qdInaDq1Zpznpmev/+52QomsJNZ3JkTl5yrTl02V6NBgJOQ4LY0SFw/8zsMwj3tLe8vqiIuwF6nxaEwgf6mg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/node-config-provider": "^4.0.1",
+ "@smithy/property-provider": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "@smithy/url-parser": "^4.0.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-codec": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.0.1.tgz",
+ "integrity": "sha512-Q2bCAAR6zXNVtJgifsU16ZjKGqdw/DyecKNgIgi7dlqw04fqDu0mnq+JmGphqheypVc64CYq3azSuCpAdFk2+A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/crc32": "5.2.0",
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-hex-encoding": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-browser": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.0.1.tgz",
+ "integrity": "sha512-HbIybmz5rhNg+zxKiyVAnvdM3vkzjE6ccrJ620iPL8IXcJEntd3hnBl+ktMwIy12Te/kyrSbUb8UCdnUT4QEdA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/eventstream-serde-universal": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-config-resolver": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.0.1.tgz",
+ "integrity": "sha512-lSipaiq3rmHguHa3QFF4YcCM3VJOrY9oq2sow3qlhFY+nBSTF/nrO82MUQRPrxHQXA58J5G1UnU2WuJfi465BA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-node": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.0.1.tgz",
+ "integrity": "sha512-o4CoOI6oYGYJ4zXo34U8X9szDe3oGjmHgsMGiZM0j4vtNoT+h80TLnkUcrLZR3+E6HIxqW+G+9WHAVfl0GXK0Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/eventstream-serde-universal": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-universal": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.0.1.tgz",
+ "integrity": "sha512-Z94uZp0tGJuxds3iEAZBqGU2QiaBHP4YytLUjwZWx+oUeohCsLyUm33yp4MMBmhkuPqSbQCXq5hDet6JGUgHWA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/eventstream-codec": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/fetch-http-handler": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.1.tgz",
+ "integrity": "sha512-3aS+fP28urrMW2KTjb6z9iFow6jO8n3MFfineGbndvzGZit3taZhKWtTorf+Gp5RpFDDafeHlhfsGlDCXvUnJA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/querystring-builder": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-base64": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/hash-blob-browser": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.0.1.tgz",
+ "integrity": "sha512-rkFIrQOKZGS6i1D3gKJ8skJ0RlXqDvb1IyAphksaFOMzkn3v3I1eJ8m7OkLj0jf1McP63rcCEoLlkAn/HjcTRw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/chunked-blob-reader": "^5.0.0",
+ "@smithy/chunked-blob-reader-native": "^4.0.0",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/hash-node": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.1.tgz",
+ "integrity": "sha512-TJ6oZS+3r2Xu4emVse1YPB3Dq3d8RkZDKcPr71Nj/lJsdAP1c7oFzYqEn1IBc915TsgLl2xIJNuxCz+gLbLE0w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-buffer-from": "^4.0.0",
+ "@smithy/util-utf8": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/hash-stream-node": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.0.1.tgz",
+ "integrity": "sha512-U1rAE1fxmReCIr6D2o/4ROqAQX+GffZpyMt3d7njtGDr2pUNmAKRWa49gsNVhCh2vVAuf3wXzWwNr2YN8PAXIw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-utf8": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/invalid-dependency": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.1.tgz",
+ "integrity": "sha512-gdudFPf4QRQ5pzj7HEnu6FhKRi61BfH/Gk5Yf6O0KiSbr1LlVhgjThcvjdu658VE6Nve8vaIWB8/fodmS1rBPQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/is-array-buffer": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.0.0.tgz",
+ "integrity": "sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/md5-js": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.0.1.tgz",
+ "integrity": "sha512-HLZ647L27APi6zXkZlzSFZIjpo8po45YiyjMGJZM3gyDY8n7dPGdmxIIljLm4gPt/7rRvutLTTkYJpZVfG5r+A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-utf8": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-content-length": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.1.tgz",
+ "integrity": "sha512-OGXo7w5EkB5pPiac7KNzVtfCW2vKBTZNuCctn++TTSOMpe6RZO/n6WEC1AxJINn3+vWLKW49uad3lo/u0WJ9oQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-endpoint": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.0.5.tgz",
+ "integrity": "sha512-cPzGZV7qStHwboFrm6GfrzQE+YDiCzWcTh4+7wKrP/ZQ4gkw+r7qDjV8GjM4N0UYsuUyLfpzLGg5hxsYTU11WA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.1.4",
+ "@smithy/middleware-serde": "^4.0.2",
+ "@smithy/node-config-provider": "^4.0.1",
+ "@smithy/shared-ini-file-loader": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "@smithy/url-parser": "^4.0.1",
+ "@smithy/util-middleware": "^4.0.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-retry": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.0.6.tgz",
+ "integrity": "sha512-s8QzuOQnbdvRymD9Gt9c9zMq10wUQAHQ3z72uirrBHCwZcLTrL5iCOuVTMdka2IXOYhQE890WD5t6G24+F+Qcg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/node-config-provider": "^4.0.1",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/service-error-classification": "^4.0.1",
+ "@smithy/smithy-client": "^4.1.5",
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-middleware": "^4.0.1",
+ "@smithy/util-retry": "^4.0.1",
+ "tslib": "^2.6.2",
+ "uuid": "^9.0.1"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-serde": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.2.tgz",
+ "integrity": "sha512-Sdr5lOagCn5tt+zKsaW+U2/iwr6bI9p08wOkCp6/eL6iMbgdtc2R5Ety66rf87PeohR0ExI84Txz9GYv5ou3iQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-stack": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.1.tgz",
+ "integrity": "sha512-dHwDmrtR/ln8UTHpaIavRSzeIk5+YZTBtLnKwDW3G2t6nAupCiQUvNzNoHBpik63fwUaJPtlnMzXbQrNFWssIA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/node-config-provider": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.0.1.tgz",
+ "integrity": "sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/property-provider": "^4.0.1",
+ "@smithy/shared-ini-file-loader": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/node-http-handler": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.2.tgz",
+ "integrity": "sha512-X66H9aah9hisLLSnGuzRYba6vckuFtGE+a5DcHLliI/YlqKrGoxhisD5XbX44KyoeRzoNlGr94eTsMVHFAzPOw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/abort-controller": "^4.0.1",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/querystring-builder": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/property-provider": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.1.tgz",
+ "integrity": "sha512-o+VRiwC2cgmk/WFV0jaETGOtX16VNPp2bSQEzu0whbReqE1BMqsP2ami2Vi3cbGVdKu1kq9gQkDAGKbt0WOHAQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/protocol-http": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.0.1.tgz",
+ "integrity": "sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/querystring-builder": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.1.tgz",
+ "integrity": "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-uri-escape": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/querystring-parser": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.1.tgz",
+ "integrity": "sha512-Ma2XC7VS9aV77+clSFylVUnPZRindhB7BbmYiNOdr+CHt/kZNJoPP0cd3QxCnCFyPXC4eybmyE98phEHkqZ5Jw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/service-error-classification": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.1.tgz",
+ "integrity": "sha512-3JNjBfOWpj/mYfjXJHB4Txc/7E4LVq32bwzE7m28GN79+M1f76XHflUaSUkhOriprPDzev9cX/M+dEB80DNDKA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/shared-ini-file-loader": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.1.tgz",
+ "integrity": "sha512-hC8F6qTBbuHRI/uqDgqqi6J0R4GtEZcgrZPhFQnMhfJs3MnUTGSnR1NSJCJs5VWlMydu0kJz15M640fJlRsIOw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/signature-v4": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.0.1.tgz",
+ "integrity": "sha512-nCe6fQ+ppm1bQuw5iKoeJ0MJfz2os7Ic3GBjOkLOPtavbD1ONoyE3ygjBfz2ythFWm4YnRm6OxW+8p/m9uCoIA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^4.0.0",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-hex-encoding": "^4.0.0",
+ "@smithy/util-middleware": "^4.0.1",
+ "@smithy/util-uri-escape": "^4.0.0",
+ "@smithy/util-utf8": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/smithy-client": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.1.5.tgz",
+ "integrity": "sha512-DMXYoYeL4QkElr216n1yodTFeATbfb4jwYM9gKn71Rw/FNA1/Sm36tkTSCsZEs7mgpG3OINmkxL9vgVFzyGPaw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.1.4",
+ "@smithy/middleware-endpoint": "^4.0.5",
+ "@smithy/middleware-stack": "^4.0.1",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-stream": "^4.1.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/types": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz",
+ "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/url-parser": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.1.tgz",
+ "integrity": "sha512-gPXcIEUtw7VlK8f/QcruNXm7q+T5hhvGu9tl63LsJPZ27exB6dtNwvh2HIi0v7JcXJ5emBxB+CJxwaLEdJfA+g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/querystring-parser": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-base64": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.0.0.tgz",
+ "integrity": "sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^4.0.0",
+ "@smithy/util-utf8": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-body-length-browser": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.0.0.tgz",
+ "integrity": "sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-body-length-node": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.0.0.tgz",
+ "integrity": "sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-buffer-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz",
+ "integrity": "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-config-provider": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.0.0.tgz",
+ "integrity": "sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-defaults-mode-browser": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.6.tgz",
+ "integrity": "sha512-N8+VCt+piupH1A7DgSVDNrVHqRLz8r6DvBkpS7EWHiIxsUk4jqGuQLjqC/gnCzmwGkVBdNruHoYAzzaSQ8e80w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/property-provider": "^4.0.1",
+ "@smithy/smithy-client": "^4.1.5",
+ "@smithy/types": "^4.1.0",
+ "bowser": "^2.11.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-defaults-mode-node": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.6.tgz",
+ "integrity": "sha512-9zhx1shd1VwSSVvLZB8CM3qQ3RPD3le7A3h/UPuyh/PC7g4OaWDi2xUNzamsVoSmCGtmUBONl56lM2EU6LcH7A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/config-resolver": "^4.0.1",
+ "@smithy/credential-provider-imds": "^4.0.1",
+ "@smithy/node-config-provider": "^4.0.1",
+ "@smithy/property-provider": "^4.0.1",
+ "@smithy/smithy-client": "^4.1.5",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-endpoints": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.1.tgz",
+ "integrity": "sha512-zVdUENQpdtn9jbpD9SCFK4+aSiavRb9BxEtw9ZGUR1TYo6bBHbIoi7VkrFQ0/RwZlzx0wRBaRmPclj8iAoJCLA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/node-config-provider": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-hex-encoding": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.0.0.tgz",
+ "integrity": "sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-middleware": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.1.tgz",
+ "integrity": "sha512-HiLAvlcqhbzhuiOa0Lyct5IIlyIz0PQO5dnMlmQ/ubYM46dPInB+3yQGkfxsk6Q24Y0n3/JmcA1v5iEhmOF5mA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-retry": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.1.tgz",
+ "integrity": "sha512-WmRHqNVwn3kI3rKk1LsKcVgPBG6iLTBGC1iYOV3GQegwJ3E8yjzHytPt26VNzOWr1qu0xE03nK0Ug8S7T7oufw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/service-error-classification": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-stream": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.1.1.tgz",
+ "integrity": "sha512-+Xvh8nhy0Wjv1y71rBVyV3eJU3356XsFQNI8dEZVNrQju7Eib8G31GWtO+zMa9kTCGd41Mflu+ZKfmQL/o2XzQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/fetch-http-handler": "^5.0.1",
+ "@smithy/node-http-handler": "^4.0.2",
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-base64": "^4.0.0",
+ "@smithy/util-buffer-from": "^4.0.0",
+ "@smithy/util-hex-encoding": "^4.0.0",
+ "@smithy/util-utf8": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-uri-escape": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz",
+ "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-utf8": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz",
+ "integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-waiter": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.0.2.tgz",
+ "integrity": "sha512-piUTHyp2Axx3p/kc2CIJkYSv0BAaheBQmbACZgQSSfWUumWNW+R1lL+H9PDBxKJkvOeEX+hKYEFiwO8xagL8AQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/abort-controller": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
"node_modules/@sveltejs/adapter-auto": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-auto/-/adapter-auto-4.0.0.tgz",
@@ -1566,6 +3134,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/bowser": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
+ "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==",
+ "license": "MIT"
+ },
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -2090,6 +3664,28 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/fast-xml-parser": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz",
+ "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ },
+ {
+ "type": "paypal",
+ "url": "https://paypal.me/naturalintelligence"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "strnum": "^1.0.5"
+ },
+ "bin": {
+ "fxparser": "src/cli/cli.js"
+ }
+ },
"node_modules/fastq": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz",
@@ -3216,6 +4812,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/strnum": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
+ "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==",
+ "license": "MIT"
+ },
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -3391,6 +4993,12 @@
"typescript": ">=4.8.4"
}
},
+ "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==",
+ "license": "0BSD"
+ },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -3465,6 +5073,19 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/uuid": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
+ "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
"node_modules/vite": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.1.0.tgz",
diff --git a/app/package.json b/app/package.json
index cf32c03..1e5986e 100644
--- a/app/package.json
+++ b/app/package.json
@@ -33,6 +33,7 @@
"vite": "^6.0.0"
},
"dependencies": {
+ "@aws-sdk/client-s3": "^3.750.0",
"pg": "^8.13.3"
}
}
diff --git a/app/src/app.d.ts b/app/src/app.d.ts
index 7844a85..b7bd0e7 100644
--- a/app/src/app.d.ts
+++ b/app/src/app.d.ts
@@ -1,4 +1,5 @@
import type { User } from "$lib/server/users";
+import type { S3Client } from "@aws-sdk/client-s3";
import type { PoolClient } from "pg";
// See https://svelte.dev/docs/kit/types#app.d.ts
@@ -9,6 +10,8 @@ declare global {
interface Locals {
dbConn: PoolClient;
+ s3Client: S3Client;
+
/**
* The user, if they are logged in.
*
diff --git a/app/src/hooks.server.ts b/app/src/hooks.server.ts
index 79535f9..8439eb3 100644
--- a/app/src/hooks.server.ts
+++ b/app/src/hooks.server.ts
@@ -1,16 +1,30 @@
import { getDbConnection } from "$lib/server/db";
+import { getS3Client } from "$lib/server/s3";
import { validateSessionToken } from "$lib/server/sessions";
-import { redirect, type Handle } from "@sveltejs/kit";
+import { type Handle } from "@sveltejs/kit";
import { sequence } from "@sveltejs/kit/hooks";
const dbHandle = (async ({ event, resolve }) => {
const dbConn = await getDbConnection();
- event.locals = { dbConn };
+ event.locals.dbConn = dbConn;
- const response = await resolve(event);
- dbConn.release();
+ try {
+ return await resolve(event);
+ } finally {
+ dbConn.release();
+ }
+}) satisfies Handle;
- return response;
+// FIXME: Kind of stupid to load for every request. Should probs move handler to $lib and import for relevant routes.
+const s3Handle = (async ({ event, resolve }) => {
+ const s3Client = getS3Client();
+ event.locals.s3Client = s3Client;
+
+ try {
+ return await resolve(event);
+ } finally {
+ s3Client.destroy();
+ }
}) satisfies Handle;
const sessionHandle = (async ({ event, resolve }) => {
@@ -25,4 +39,4 @@ const sessionHandle = (async ({ event, resolve }) => {
return resolve(event);
}) satisfies Handle;
-export const handle = sequence(dbHandle, sessionHandle);
+export const handle = sequence(dbHandle, s3Handle, sessionHandle);
diff --git a/app/src/lib/common/assignments.ts b/app/src/lib/common/assignments.ts
new file mode 100644
index 0000000..79553cd
--- /dev/null
+++ b/app/src/lib/common/assignments.ts
@@ -0,0 +1,32 @@
+/** A row from the `cemetary_plot` table. */
+export interface CemetaryPlot {
+ id: number;
+ address: string;
+ ownerId: number;
+ //assignmentInterval: Date;
+}
+
+/** Corresponds to `assignment_state`. */
+export type AssignmentState = "AWAITING_GARDENER_NOTIFICATION"
+ | "AWAITING_FINISH"
+ | "AWAITING_WATERMARKING"
+ | "AWAITING_OWNER_NOTIFICATION"
+ | "DONE"
+ ;
+
+/** A row from the `assignments` table. */
+export interface Assignment {
+ id: number;
+ gardenerId: number;
+ cemetaryPlotId: number;
+ date: Date;
+ state: AssignmentState;
+}
+
+
+// FIXME: We have ORM at home. A more clearly defined (OOP) model layer.
+/** Checks whether the state of the assignment allows it to be "finished". */
+export function canBeFinished(assignment: Assignment): boolean {
+ return (assignment.state === "AWAITING_GARDENER_NOTIFICATION" ||
+ assignment.state === "AWAITING_FINISH")
+}
diff --git a/app/src/lib/server/assignments.ts b/app/src/lib/server/assignments.ts
index 7622408..787865c 100644
--- a/app/src/lib/server/assignments.ts
+++ b/app/src/lib/server/assignments.ts
@@ -1,20 +1,6 @@
-import type pg from "pg";
-
-/** A row from the `cemetary_plot` table. */
-export interface CemetaryPlot {
- id: number;
- address: string;
- ownerId: number;
- //assignmentInterval: Date;
-}
-
-/** A row from the `assignments` table. */
-export interface Assignment {
- id: number;
- gardenerId: number;
- cemetaryPlotId: number;
- date: Date;
-}
+import { PutObjectCommand, type S3Client } from "@aws-sdk/client-s3"; /*=;* /
+import type { ClientBase } from "pg";
+import type { CemetaryPlot, Assignment, AssignmentState } from "../common/assignments";
/**
* Retrieves all assignments for the given user.
@@ -22,7 +8,7 @@ export interface Assignment {
* @param dbConn Connection to database.
* @param userId ID used to identify user.
*/
-export async function getAssignments(dbConn: pg.ClientBase, userId: number): Promise<Assignment[]> {
+export async function getAssignments(dbConn: ClientBase, userId: number): Promise<Assignment[]> {
const result = await dbConn.query(
"SELECT * FROM assignments WHERE gardener_id = $1 ORDER BY date",
[userId],
@@ -34,6 +20,7 @@ export async function getAssignments(dbConn: pg.ClientBase, userId: number): Pro
gardenerId: r.gardener_id,
cemetaryPlotId: r.cemetary_plot_id,
date: r.date,
+ state: r.state,
}) satisfies Assignment,
);
}
@@ -46,7 +33,7 @@ type GetAssignmentResult =
* Retrieves a specfic assignment, along with relevant cemetary plot.
*/
export async function getAssignmentAndCemetaryById(
- dbConn: pg.ClientBase,
+ dbConn: ClientBase,
assignmentId: number,
): Promise<GetAssignmentResult> {
const queryText = `SELECT
@@ -54,6 +41,7 @@ export async function getAssignmentAndCemetaryById(
a.gardener_id,
a.cemetary_plot_id,
a.date,
+ a.state,
c.id,
c.address,
c.owner_id,
@@ -73,12 +61,84 @@ export async function getAssignmentAndCemetaryById(
gardenerId: result.rows[0][1],
cemetaryPlotId: result.rows[0][2],
date: result.rows[0][3],
+ state: result.rows[0][4],
};
const cemetaryPlot: CemetaryPlot = {
- id: result.rows[0][4],
- address: result.rows[0][5],
- ownerId: result.rows[0][6],
- //assignmentInterval: result.rows[0][7],
+ id: result.rows[0][5],
+ address: result.rows[0][6],
+ ownerId: result.rows[0][7],
+ //assignmentInterval: result.rows[0][8],
};
return { assignment, cemetaryPlot };
}
+
+export interface FinishAssignmentArgs {
+ images: { bytes: Uint8Array; name: string }[];
+ note?: string;
+ assignmentId: number;
+}
+
+// TODO: Error recovery.
+export async function finishAssignment(
+ dbConn: ClientBase,
+ s3Client: S3Client,
+ { images, note, assignmentId }: FinishAssignmentArgs,
+): Promise<void> {
+ // Upload to S3, returning path
+ // FIXME: Should be factored out?
+ const uploadPromises = images.map(async (image) => {
+ const key = generateImageKey();
+
+ const cmd = new PutObjectCommand({
+ Bucket: "images",
+ Key: key,
+ Body: image.bytes,
+ IfNoneMatch: "*", // Error, in case of key collision.
+ });
+
+ await s3Client.send(cmd);
+ return { ...image, key };
+ });
+ const uploadedImages = await Promise.all(uploadPromises);
+
+ // TODO: Add beanstalkd job
+
+ await dbConn.query("BEGIN");
+
+ try {
+ // Create 'images' row for each image.
+ // FIXME: Apparently node-pg doesn't have an equivalent to Python's `insert_many`??
+ for (const image of uploadedImages) {
+ dbConn.query({
+ name: "insert-assignment-image",
+ text: "INSERT INTO images(s3_path, original_filename, assignment_id) VALUES ($1, $2, $3)",
+ values: [image.key, image.name, assignmentId],
+ });
+ }
+
+ // Update the assingment's state.
+ dbConn.query(
+ `UPDATE
+ assignments
+ SET
+ state = 'AWAITING_WATERMARKING' :: assignment_state,
+ note = $1
+ WHERE
+ id = $2`,
+ [note, assignmentId],
+ );
+
+ dbConn.query("COMMIT");
+ } catch (err) {
+ // We should probably try to delete S3 objects.
+
+ // We should probably try to delete the job.
+
+ await dbConn.query("ROLLBACK");
+ throw err;
+ }
+}
+
+function generateImageKey(): string {
+ return crypto.randomUUID();
+}
diff --git a/app/src/lib/server/s3.ts b/app/src/lib/server/s3.ts
new file mode 100644
index 0000000..a1a28fa
--- /dev/null
+++ b/app/src/lib/server/s3.ts
@@ -0,0 +1,16 @@
+import { S3Client } from "@aws-sdk/client-s3";
+
+// We would obviously read from .env in prod, but it's an annoying indirection for this demo.
+export function getS3Client(): S3Client {
+ const client = new S3Client({
+ endpoint: "http://localhost:9000",
+ region: "us-east-1", // Required, but ignored for local usage.
+ credentials: {
+ accessKeyId: "minioadmin",
+ secretAccessKey: "minioadmin",
+ },
+ forcePathStyle: true, // Required for local service since we obv. can't use subdomains.
+ });
+
+ return client;
+}
diff --git a/app/src/lib/server/sessions.ts b/app/src/lib/server/sessions.ts
index 0ca46e0..69a8b46 100644
--- a/app/src/lib/server/sessions.ts
+++ b/app/src/lib/server/sessions.ts
@@ -88,7 +88,7 @@ export async function validateSessionToken(
WHERE token = $1;`,
[token],
);
- console.debug(result);
+ //console.debug(result);
if (result.rowCount === 0) {
return { session: null, user: null };
}
@@ -105,7 +105,7 @@ export async function validateSessionToken(
lastName: result.rows[0].last_name,
role: result.rows[0].role,
};
- console.debug("Session with token %s: %o, %o", token, session, user);
+ //console.debug("Session with token %s: %o, %o", token, session, user);
// Step 2.
const now = Date.now();
diff --git a/app/src/routes/assignments/[assignmentId]/+page.server.ts b/app/src/routes/assignments/[assignmentId]/+page.server.ts
index 566dcd9..280c5bd 100644
--- a/app/src/routes/assignments/[assignmentId]/+page.server.ts
+++ b/app/src/routes/assignments/[assignmentId]/+page.server.ts
@@ -1,5 +1,5 @@
-import { getAssignmentAndCemetaryById } from "$lib/server/assignments";
-import type { PageServerLoad } from "./$types";
+import { finishAssignment, getAssignmentAndCemetaryById } from "$lib/server/assignments";
+import type { PageServerLoad, Actions } from "./$types";
import { error, redirect } from "@sveltejs/kit";
export const load = (async ({ params, url, locals }) => {
@@ -25,3 +25,29 @@ export const load = (async ({ params, url, locals }) => {
cemetaryPlot,
};
}) satisfies PageServerLoad;
+
+export const actions = {
+ // FIXME: Skipped input validation.
+ // FIXME: Is 'load' action run (wrt. authentication)?
+ finish: async ({ params, request, locals }) => {
+ const formData = await request.formData();
+ const imageFiles = formData.getAll("images") as File[];
+ const note = (formData.get("note") as string | null) ?? undefined;
+
+ // Read image files in parallel.
+ const images = await Promise.all(
+ imageFiles.map(async (f) => ({
+ name: f.name,
+ bytes: new Uint8Array(await f.arrayBuffer()),
+ })),
+ );
+
+ await finishAssignment(locals.dbConn, locals.s3Client, {
+ images,
+ note,
+ assignmentId: +params.assignmentId, // We have parsing at home...
+ });
+
+ return { success: true };
+ },
+} satisfies Actions;
diff --git a/app/src/routes/assignments/[assignmentId]/+page.svelte b/app/src/routes/assignments/[assignmentId]/+page.svelte
index 0b36a19..9cf9890 100644
--- a/app/src/routes/assignments/[assignmentId]/+page.svelte
+++ b/app/src/routes/assignments/[assignmentId]/+page.svelte
@@ -1,5 +1,7 @@
<script lang="ts">
+ import { enhance } from "$app/forms";
import type { PageProps } from "./$types";
+ import { canBeFinished } from "$lib/common/assignments";
let { data }: PageProps = $props();
@@ -12,14 +14,38 @@
<h1>Assignment #{data.assignment.id}</h1>
<p>
- Gravstedet, der skal vedligeholdes er ved <span class="address">{data.cemetaryPlot.address}</span
- >.
+ Gravstedet, der skal vedligeholdes er ved
+ <span class="address">{data.cemetaryPlot.address}</span>.
</p>
<p>Vedligeholdelsen skal finde sted <time>{assignmentDate}<time>.</time></time></p>
+<p>State: {data.assignment.state}</p>
+
+<h2>Færdiggør opgave</h2>
+{#if canBeFinished(data.assignment)}
+ <p>Når du har færdiggjort opgaven, kan du uploade billederne her:</p>
+ <form method="POST" action="?/finish" enctype="multipart/form-data" use:enhance>
+ <label>
+ Billeder:
+ <input type="file" name="images" accept=".jpg, .jpeg, .png, .webp" required multiple />
+ </label>
+ <label>
+ Ekstra bemærkninger:
+ <textarea name="notes" placeholder="F.eks.: Vi løb tør for roser (?). De kommer i overmorgen :)"
+ ></textarea>
+ </label>
+ <button>Færddigør job</button>
+ </form>
+{:else}
+ <p>Du har færddigjort denne opgave!</p>
+{/if}
<style>
.address,
time {
font-weight: bold;
}
+
+ label {
+ display: block;
+ }
</style>
diff --git a/db/dump.sql b/db/dump.sql
index 5cb3a51..9486eb6 100644
--- a/db/dump.sql
+++ b/db/dump.sql
@@ -32,6 +32,28 @@ COMMENT ON EXTENSION pgcrypto IS 'cryptographic functions';
--
+-- Name: assignment_state; Type: TYPE; Schema: public; Owner: postgres
+--
+
+CREATE TYPE public.assignment_state AS ENUM (
+ 'AWAITING_GARDENER_NOTIFICATION',
+ 'AWAITING_FINISH',
+ 'AWAITING_WATERMARKING',
+ 'AWAITING_OWNER_NOTIFICATION',
+ 'DONE'
+);
+
+
+ALTER TYPE public.assignment_state OWNER TO postgres;
+
+--
+-- Name: TYPE assignment_state; Type: COMMENT; Schema: public; Owner: postgres
+--
+
+COMMENT ON TYPE public.assignment_state IS 'The states for an assignment.';
+
+
+--
-- Name: role; Type: TYPE; Schema: public; Owner: postgres
--
@@ -55,6 +77,120 @@ SET default_tablespace = '';
SET default_table_access_method = heap;
--
+-- Name: assignments; Type: TABLE; Schema: public; Owner: postgres
+--
+
+CREATE TABLE public.assignments (
+ id integer NOT NULL,
+ gardener_id integer NOT NULL,
+ cemetary_plot_id integer NOT NULL,
+ date date,
+ state public.assignment_state DEFAULT 'AWAITING_GARDENER_NOTIFICATION'::public.assignment_state NOT NULL,
+ note text
+);
+
+
+ALTER TABLE public.assignments OWNER TO postgres;
+
+--
+-- Name: COLUMN assignments.note; Type: COMMENT; Schema: public; Owner: postgres
+--
+
+COMMENT ON COLUMN public.assignments.note IS 'When an assignment is finished, the gardener can supply a note.';
+
+
+--
+-- Name: assignments_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
+--
+
+ALTER TABLE public.assignments ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY (
+ SEQUENCE NAME public.assignments_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1
+);
+
+
+--
+-- Name: cemetary_plots; Type: TABLE; Schema: public; Owner: postgres
+--
+
+CREATE TABLE public.cemetary_plots (
+ id integer NOT NULL,
+ address text NOT NULL,
+ owner_id integer NOT NULL,
+ assignment_interval interval day DEFAULT '14 days'::interval NOT NULL
+);
+
+
+ALTER TABLE public.cemetary_plots OWNER TO postgres;
+
+--
+-- Name: COLUMN cemetary_plots.assignment_interval; Type: COMMENT; Schema: public; Owner: postgres
+--
+
+COMMENT ON COLUMN public.cemetary_plots.assignment_interval IS 'The interval between when cleaning assignments. If there was a job at time N, the next one would be at N + assignment_interval.';
+
+
+--
+-- Name: cementary_plots_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
+--
+
+ALTER TABLE public.cemetary_plots ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY (
+ SEQUENCE NAME public.cementary_plots_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1
+);
+
+
+--
+-- Name: images; Type: TABLE; Schema: public; Owner: postgres
+--
+
+CREATE TABLE public.images (
+ id integer NOT NULL,
+ s3_path text NOT NULL,
+ original_filename text NOT NULL,
+ assignment_id integer
+);
+
+
+ALTER TABLE public.images OWNER TO postgres;
+
+--
+-- Name: TABLE images; Type: COMMENT; Schema: public; Owner: postgres
+--
+
+COMMENT ON TABLE public.images IS 'This table stores the images uploaded when finishing an assignment.';
+
+
+--
+-- Name: COLUMN images.assignment_id; Type: COMMENT; Schema: public; Owner: postgres
+--
+
+COMMENT ON COLUMN public.images.assignment_id IS 'Reference to the owning assignment';
+
+
+--
+-- Name: images_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
+--
+
+ALTER TABLE public.images ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY (
+ SEQUENCE NAME public.images_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1
+);
+
+
+--
-- Name: sessions; Type: TABLE; Schema: public; Owner: postgres
--
@@ -105,12 +241,44 @@ ALTER TABLE public.users ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY (
--
+-- Data for Name: assignments; Type: TABLE DATA; Schema: public; Owner: postgres
+--
+
+COPY public.assignments (id, gardener_id, cemetary_plot_id, date, state, note) FROM stdin;
+2 1 2 2025-03-05 AWAITING_GARDENER_NOTIFICATION \N
+1 1 1 2025-02-28 AWAITING_WATERMARKING \N
+\.
+
+
+--
+-- Data for Name: cemetary_plots; Type: TABLE DATA; Schema: public; Owner: postgres
+--
+
+COPY public.cemetary_plots (id, address, owner_id, assignment_interval) FROM stdin;
+1 24B, Kirkevej 64, Egå 8328 4 21 days
+2 26C, Kirkevej 64, Egå 8328 5 14 days
+\.
+
+
+--
+-- Data for Name: images; Type: TABLE DATA; Schema: public; Owner: postgres
+--
+
+COPY public.images (id, s3_path, original_filename, assignment_id) FROM stdin;
+3 fe5e7c27-99c4-4d4b-ba77-fcad5c6607e3 eva.jpeg 1
+\.
+
+
+--
-- Data for Name: sessions; Type: TABLE DATA; Schema: public; Owner: postgres
--
COPY public.sessions (token, user_id, expires_at) FROM stdin;
je2bic5i5jou7woob4ehreoqojuir4co 1 2025-03-19 18:04:35.904+01
27ghlb4vzh543kxpnkniip2oai6q4dvx 1 2025-03-19 18:04:47.722+01
+bjt7wgbfrlzrg7fhphsxezpc7fornezv 1 2025-03-19 20:42:57.838+01
+bgrgdtxmiq44ig6dh32pop4wkterqj6r 1 2025-03-20 18:03:54.199+01
+q6ifvlkjdoncw5usnb37da3sf4y3fxyq 1 2025-03-20 20:01:53.318+01
\.
@@ -122,14 +290,54 @@ COPY public.users (id, role, first_name, last_name, password_hash, email) FROM s
1 gardener Emil Blomst $2a$06$vw1iVTLDQzeUwmhyW17ZzeJL.gyC4xWWzAwvJO8dsZi7Jdg2w5zbu [email protected]
2 gardener Sarah Hækkesen $2a$06$RyzzMad/jmKZwg9hRDymCO/KvxiSUFcdYQZdxB9trHHOU3tKhtFIK sarah.hækkesen@kirkefætrene.dk
3 gardener Sten Graversen $2a$06$/InJ2HFv1/z0YVXMwoHWZuV7aTlWl3GH9csKEvN5gb4nEPSECEdFq [email protected]
+4 owner Lotte Ejersen $2a$06$C1JTdp2y9lIO57S7kGsBruE2oLj87AYpNNrZqx/5Zgap5lqcDj.my [email protected]
+5 owner Mads Hylgaard Jensen $2a$06$FuFHsoFo1cPJ9ms9TceVG..2BAHAyJpE2NyBUTH9JnG6v8GWuOh4u [email protected]
+6 owner Lukas Ibasen $2a$06$p2nOFXtLC0YE/7TTxqzUOeEfpPKVjVZr2sge1KBFT/7lrx2rpsvO2 [email protected]
\.
--
+-- Name: assignments_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres
+--
+
+SELECT pg_catalog.setval('public.assignments_id_seq', 2, true);
+
+
+--
+-- Name: cementary_plots_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres
+--
+
+SELECT pg_catalog.setval('public.cementary_plots_id_seq', 2, true);
+
+
+--
+-- Name: images_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres
+--
+
+SELECT pg_catalog.setval('public.images_id_seq', 3, true);
+
+
+--
-- Name: users_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres
--
-SELECT pg_catalog.setval('public.users_id_seq', 3, true);
+SELECT pg_catalog.setval('public.users_id_seq', 6, true);
+
+
+--
+-- Name: assignments assignments_id_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
+--
+
+ALTER TABLE ONLY public.assignments
+ ADD CONSTRAINT assignments_id_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: cemetary_plots cemetary_plots_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
+--
+
+ALTER TABLE ONLY public.cemetary_plots
+ ADD CONSTRAINT cemetary_plots_pkey PRIMARY KEY (id);
--
@@ -148,6 +356,14 @@ COMMENT ON CONSTRAINT email_uniqueness ON public.users IS 'Multiple users cannot
--
+-- Name: images images_s3_path_key; Type: CONSTRAINT; Schema: public; Owner: postgres
+--
+
+ALTER TABLE ONLY public.images
+ ADD CONSTRAINT images_s3_path_key UNIQUE (s3_path);
+
+
+--
-- Name: sessions sessions_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--
@@ -164,6 +380,38 @@ ALTER TABLE ONLY public.users
--
+-- Name: assignments assignments_cemetary_plot_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: postgres
+--
+
+ALTER TABLE ONLY public.assignments
+ ADD CONSTRAINT assignments_cemetary_plot_id_fkey FOREIGN KEY (cemetary_plot_id) REFERENCES public.cemetary_plots(id);
+
+
+--
+-- Name: assignments assignments_gardener_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: postgres
+--
+
+ALTER TABLE ONLY public.assignments
+ ADD CONSTRAINT assignments_gardener_id_fkey FOREIGN KEY (gardener_id) REFERENCES public.users(id);
+
+
+--
+-- Name: cemetary_plots cemetary_plots_owner_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: postgres
+--
+
+ALTER TABLE ONLY public.cemetary_plots
+ ADD CONSTRAINT cemetary_plots_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES public.users(id);
+
+
+--
+-- Name: images images_assignment_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: postgres
+--
+
+ALTER TABLE ONLY public.images
+ ADD CONSTRAINT images_assignment_id_fkey FOREIGN KEY (assignment_id) REFERENCES public.assignments(id) ON UPDATE CASCADE ON DELETE CASCADE;
+
+
+--
-- Name: sessions sessions_userid_fkey; Type: FK CONSTRAINT; Schema: public; Owner: postgres
--