diff --git a/package-lock.json b/package-lock.json index 0253097..6237ef2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,6 @@ "name": "volunchain-backend", "version": "1.0.0", "dependencies": { - "@aws-sdk/client-s3": "^3.798.0", "@aws-sdk/s3-request-presigner": "^3.798.0", "@prisma/client": "^6.4.1", "@stellar/stellar-sdk": "^13.3.0", @@ -18,7 +17,6 @@ "@types/swagger-ui-express": "^4.1.7", "@types/uuid": "^10.0.0", "axios": "^1.7.9", - "backblaze-b2": "^1.7.0", "bcryptjs": "^3.0.2", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", @@ -29,7 +27,6 @@ "express-rate-limit": "^7.5.0", "express-validator": "^7.2.0", "jsonwebtoken": "^9.0.2", - "multer": "^1.4.5-lts.2", "node-cron": "^3.0.3", "nodemailer": "^6.10.0", "pdf-lib": "^1.17.1", @@ -133,715 +130,47 @@ "openapi-types": ">=7" } }, - "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.798.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.798.0.tgz", - "integrity": "sha512-MmVWlRK8n7cAfdtcNK7KAhiSbMt2KBLAcnvIpDx37jpQGjEe/ahQ6xOi9r1JdNaIg4SyMZsbmeLVtvDntwlxqQ==", - "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.798.0", - "@aws-sdk/credential-provider-node": "3.798.0", - "@aws-sdk/middleware-bucket-endpoint": "3.775.0", - "@aws-sdk/middleware-expect-continue": "3.775.0", - "@aws-sdk/middleware-flexible-checksums": "3.798.0", - "@aws-sdk/middleware-host-header": "3.775.0", - "@aws-sdk/middleware-location-constraint": "3.775.0", - "@aws-sdk/middleware-logger": "3.775.0", - "@aws-sdk/middleware-recursion-detection": "3.775.0", - "@aws-sdk/middleware-sdk-s3": "3.798.0", - "@aws-sdk/middleware-ssec": "3.775.0", - "@aws-sdk/middleware-user-agent": "3.798.0", - "@aws-sdk/region-config-resolver": "3.775.0", - "@aws-sdk/signature-v4-multi-region": "3.798.0", - "@aws-sdk/types": "3.775.0", - "@aws-sdk/util-endpoints": "3.787.0", - "@aws-sdk/util-user-agent-browser": "3.775.0", - "@aws-sdk/util-user-agent-node": "3.798.0", - "@aws-sdk/xml-builder": "3.775.0", - "@smithy/config-resolver": "^4.1.0", - "@smithy/core": "^3.3.0", - "@smithy/eventstream-serde-browser": "^4.0.2", - "@smithy/eventstream-serde-config-resolver": "^4.1.0", - "@smithy/eventstream-serde-node": "^4.0.2", - "@smithy/fetch-http-handler": "^5.0.2", - "@smithy/hash-blob-browser": "^4.0.2", - "@smithy/hash-node": "^4.0.2", - "@smithy/hash-stream-node": "^4.0.2", - "@smithy/invalid-dependency": "^4.0.2", - "@smithy/md5-js": "^4.0.2", - "@smithy/middleware-content-length": "^4.0.2", - "@smithy/middleware-endpoint": "^4.1.1", - "@smithy/middleware-retry": "^4.1.1", - "@smithy/middleware-serde": "^4.0.3", - "@smithy/middleware-stack": "^4.0.2", - "@smithy/node-config-provider": "^4.0.2", - "@smithy/node-http-handler": "^4.0.4", - "@smithy/protocol-http": "^5.1.0", - "@smithy/smithy-client": "^4.2.1", - "@smithy/types": "^4.2.0", - "@smithy/url-parser": "^4.0.2", - "@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.9", - "@smithy/util-defaults-mode-node": "^4.0.9", - "@smithy/util-endpoints": "^3.0.2", - "@smithy/util-middleware": "^4.0.2", - "@smithy/util-retry": "^4.0.2", - "@smithy/util-stream": "^4.2.0", - "@smithy/util-utf8": "^4.0.0", - "@smithy/util-waiter": "^4.0.3", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-sso": { - "version": "3.798.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.798.0.tgz", - "integrity": "sha512-Si4W7kFflNXC48lr05n2Fc5nrD6whbfgR7c5/7hYSXP52DOqy2kMle+bZx5EkmQ/e/5nAPW0DS4ABeLprVSghw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.798.0", - "@aws-sdk/middleware-host-header": "3.775.0", - "@aws-sdk/middleware-logger": "3.775.0", - "@aws-sdk/middleware-recursion-detection": "3.775.0", - "@aws-sdk/middleware-user-agent": "3.798.0", - "@aws-sdk/region-config-resolver": "3.775.0", - "@aws-sdk/types": "3.775.0", - "@aws-sdk/util-endpoints": "3.787.0", - "@aws-sdk/util-user-agent-browser": "3.775.0", - "@aws-sdk/util-user-agent-node": "3.798.0", - "@smithy/config-resolver": "^4.1.0", - "@smithy/core": "^3.3.0", - "@smithy/fetch-http-handler": "^5.0.2", - "@smithy/hash-node": "^4.0.2", - "@smithy/invalid-dependency": "^4.0.2", - "@smithy/middleware-content-length": "^4.0.2", - "@smithy/middleware-endpoint": "^4.1.1", - "@smithy/middleware-retry": "^4.1.1", - "@smithy/middleware-serde": "^4.0.3", - "@smithy/middleware-stack": "^4.0.2", - "@smithy/node-config-provider": "^4.0.2", - "@smithy/node-http-handler": "^4.0.4", - "@smithy/protocol-http": "^5.1.0", - "@smithy/smithy-client": "^4.2.1", - "@smithy/types": "^4.2.0", - "@smithy/url-parser": "^4.0.2", - "@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.9", - "@smithy/util-defaults-mode-node": "^4.0.9", - "@smithy/util-endpoints": "^3.0.2", - "@smithy/util-middleware": "^4.0.2", - "@smithy/util-retry": "^4.0.2", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/core": { - "version": "3.798.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.798.0.tgz", - "integrity": "sha512-hITxDE4pVkeJqz0LXjQRDgR+noxJ5oOxG38fgmQXjPXsdwVKnNIiMJ5S2WFMVSszU7ebGSyHdPHENQKu6TReVA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.775.0", - "@smithy/core": "^3.3.0", - "@smithy/node-config-provider": "^4.0.2", - "@smithy/property-provider": "^4.0.2", - "@smithy/protocol-http": "^5.1.0", - "@smithy/signature-v4": "^5.1.0", - "@smithy/smithy-client": "^4.2.1", - "@smithy/types": "^4.2.0", - "@smithy/util-middleware": "^4.0.2", - "fast-xml-parser": "4.4.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.798.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.798.0.tgz", - "integrity": "sha512-EsfzTEeoaHY1E+g3S6AmC3bF6euZN5SrLcLh5Oxhx5q2qjWUsKEK0fwek+jlt2GH7zB3F9IArV4z+8CsDQdKYw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.798.0", - "@aws-sdk/types": "3.775.0", - "@smithy/property-provider": "^4.0.2", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.798.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.798.0.tgz", - "integrity": "sha512-bw5TmcJqpBVQlXzkL63545iHQ9mxwQeXTS/rgUQ5rmNNS3yiGDekVZOLXo/Gs4wmt2/59UN/sWIRFxvxDpMQEg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.798.0", - "@aws-sdk/types": "3.775.0", - "@smithy/fetch-http-handler": "^5.0.2", - "@smithy/node-http-handler": "^4.0.4", - "@smithy/property-provider": "^4.0.2", - "@smithy/protocol-http": "^5.1.0", - "@smithy/smithy-client": "^4.2.1", - "@smithy/types": "^4.2.0", - "@smithy/util-stream": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.798.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.798.0.tgz", - "integrity": "sha512-zqWwKhhdf5CVRL6+4vNNTZVHWH9OiiwUWA3ka44jJaAMBRbbryjRedzwkWbgDaL1EbfTbcBZTYzE7N/vK7UUVA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.798.0", - "@aws-sdk/credential-provider-env": "3.798.0", - "@aws-sdk/credential-provider-http": "3.798.0", - "@aws-sdk/credential-provider-process": "3.798.0", - "@aws-sdk/credential-provider-sso": "3.798.0", - "@aws-sdk/credential-provider-web-identity": "3.798.0", - "@aws-sdk/nested-clients": "3.798.0", - "@aws-sdk/types": "3.775.0", - "@smithy/credential-provider-imds": "^4.0.2", - "@smithy/property-provider": "^4.0.2", - "@smithy/shared-ini-file-loader": "^4.0.2", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.798.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.798.0.tgz", - "integrity": "sha512-Mrhl4wS4lMpuw2NCga5/rtQehNfyRs8NUHfvrLK5bZvJbjanrh8QtdRVhrAjw71OwFh3GK49QMByGkUssALJ+g==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.798.0", - "@aws-sdk/credential-provider-http": "3.798.0", - "@aws-sdk/credential-provider-ini": "3.798.0", - "@aws-sdk/credential-provider-process": "3.798.0", - "@aws-sdk/credential-provider-sso": "3.798.0", - "@aws-sdk/credential-provider-web-identity": "3.798.0", - "@aws-sdk/types": "3.775.0", - "@smithy/credential-provider-imds": "^4.0.2", - "@smithy/property-provider": "^4.0.2", - "@smithy/shared-ini-file-loader": "^4.0.2", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.798.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.798.0.tgz", - "integrity": "sha512-BbRq8bhCHC94OTRIg5edgGTaWUzBH0h/IZJZ0vERle8A9nfl+5jUplvC8cvh3/8cNgHIRXj5HzlDjeSVe9dySg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.798.0", - "@aws-sdk/types": "3.775.0", - "@smithy/property-provider": "^4.0.2", - "@smithy/shared-ini-file-loader": "^4.0.2", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.798.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.798.0.tgz", - "integrity": "sha512-MLpQRb7xkqI9w0slEA76QiHGzM0PDMcpVcQG0wFHrpLKkQYjYlD9H3VfxdYGUh+FPOaR1fFpRZb18Gz9MR/2eQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/client-sso": "3.798.0", - "@aws-sdk/core": "3.798.0", - "@aws-sdk/token-providers": "3.798.0", - "@aws-sdk/types": "3.775.0", - "@smithy/property-provider": "^4.0.2", - "@smithy/shared-ini-file-loader": "^4.0.2", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.798.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.798.0.tgz", - "integrity": "sha512-OWBDy/ZiC0pxLzp1Nhah5jxDZ/onLTjouIVGPyc9E8/KzUJxqQbR6fk43VqhpYdVp/S7yDDbaOpO072RRZJQrw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.798.0", - "@aws-sdk/nested-clients": "3.798.0", - "@aws-sdk/types": "3.775.0", - "@smithy/property-provider": "^4.0.2", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-bucket-endpoint": { - "version": "3.775.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.775.0.tgz", - "integrity": "sha512-qogMIpVChDYr4xiUNC19/RDSw/sKoHkAhouS6Skxiy6s27HBhow1L3Z1qVYXuBmOZGSWPU0xiyZCvOyWrv9s+Q==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.775.0", - "@aws-sdk/util-arn-parser": "3.723.0", - "@smithy/node-config-provider": "^4.0.2", - "@smithy/protocol-http": "^5.1.0", - "@smithy/types": "^4.2.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.775.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.775.0.tgz", - "integrity": "sha512-Apd3owkIeUW5dnk3au9np2IdW2N0zc9NjTjHiH+Mx3zqwSrc+m+ANgJVgk9mnQjMzU/vb7VuxJ0eqdEbp5gYsg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.775.0", - "@smithy/protocol-http": "^5.1.0", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-flexible-checksums": { - "version": "3.798.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.798.0.tgz", - "integrity": "sha512-NR3YdVq2IiVYq5mLn5DpTLFSvz3+G78dE7RtWk6Jv2FCflXiWersU9lg4zisOQxHkwDy10lVlxQUlEJdJk0EQg==", - "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.798.0", - "@aws-sdk/types": "3.775.0", - "@smithy/is-array-buffer": "^4.0.0", - "@smithy/node-config-provider": "^4.0.2", - "@smithy/protocol-http": "^5.1.0", - "@smithy/types": "^4.2.0", - "@smithy/util-middleware": "^4.0.2", - "@smithy/util-stream": "^4.2.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.775.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.775.0.tgz", - "integrity": "sha512-tkSegM0Z6WMXpLB8oPys/d+umYIocvO298mGvcMCncpRl77L9XkvSLJIFzaHes+o7djAgIduYw8wKIMStFss2w==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.775.0", - "@smithy/protocol-http": "^5.1.0", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-location-constraint": { - "version": "3.775.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.775.0.tgz", - "integrity": "sha512-8TMXEHZXZTFTckQLyBT5aEI8fX11HZcwZseRifvBKKpj0RZDk4F0EEYGxeNSPpUQ7n+PRWyfAEnnZNRdAj/1NQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.775.0", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-logger": { - "version": "3.775.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.775.0.tgz", - "integrity": "sha512-FaxO1xom4MAoUJsldmR92nT1G6uZxTdNYOFYtdHfd6N2wcNaTuxgjIvqzg5y7QIH9kn58XX/dzf1iTjgqUStZw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.775.0", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.775.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.775.0.tgz", - "integrity": "sha512-GLCzC8D0A0YDG5u3F5U03Vb9j5tcOEFhr8oc6PDk0k0vm5VwtZOE6LvK7hcCSoAB4HXyOUM0sQuXrbaAh9OwXA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.775.0", - "@smithy/protocol-http": "^5.1.0", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.798.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.798.0.tgz", - "integrity": "sha512-UvficjDO/Vrxd1xufR+5ey8NdDUrvIuiEWP/uu4kOkUTXk3IR89F+5UbYWSadhkysbyWN3tui09bWbIbq2Vhag==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.798.0", - "@aws-sdk/types": "3.775.0", - "@aws-sdk/util-arn-parser": "3.723.0", - "@smithy/core": "^3.3.0", - "@smithy/node-config-provider": "^4.0.2", - "@smithy/protocol-http": "^5.1.0", - "@smithy/signature-v4": "^5.1.0", - "@smithy/smithy-client": "^4.2.1", - "@smithy/types": "^4.2.0", - "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.2", - "@smithy/util-stream": "^4.2.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-ssec": { - "version": "3.775.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.775.0.tgz", - "integrity": "sha512-Iw1RHD8vfAWWPzBBIKaojO4GAvQkHOYIpKdAfis/EUSUmSa79QsnXnRqsdcE0mCB0Ylj23yi+ah4/0wh9FsekA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.775.0", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.798.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.798.0.tgz", - "integrity": "sha512-nb3YvLokpu/2meKVH5hGVLNg+hz3IyFCESEJW+SpK7bW/SfaKpukGY1lqwqbf+edl+s20MRXeK/by1rvBChixQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.798.0", - "@aws-sdk/types": "3.775.0", - "@aws-sdk/util-endpoints": "3.787.0", - "@smithy/core": "^3.3.0", - "@smithy/protocol-http": "^5.1.0", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/nested-clients": { + "node_modules/@aws-sdk/core": { "version": "3.798.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.798.0.tgz", - "integrity": "sha512-14iBJgg2Qqf74IeUY+z1nP5GIJIBZj8lv9mdpXrHlK8k+FcMXjpHg/B+JguSMhb2sbLeb5N0H8HLJGIRNALVWw==", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.798.0.tgz", + "integrity": "sha512-hITxDE4pVkeJqz0LXjQRDgR+noxJ5oOxG38fgmQXjPXsdwVKnNIiMJ5S2WFMVSszU7ebGSyHdPHENQKu6TReVA==", "license": "Apache-2.0", "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.798.0", - "@aws-sdk/middleware-host-header": "3.775.0", - "@aws-sdk/middleware-logger": "3.775.0", - "@aws-sdk/middleware-recursion-detection": "3.775.0", - "@aws-sdk/middleware-user-agent": "3.798.0", - "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/types": "3.775.0", - "@aws-sdk/util-endpoints": "3.787.0", - "@aws-sdk/util-user-agent-browser": "3.775.0", - "@aws-sdk/util-user-agent-node": "3.798.0", - "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.3.0", - "@smithy/fetch-http-handler": "^5.0.2", - "@smithy/hash-node": "^4.0.2", - "@smithy/invalid-dependency": "^4.0.2", - "@smithy/middleware-content-length": "^4.0.2", - "@smithy/middleware-endpoint": "^4.1.1", - "@smithy/middleware-retry": "^4.1.1", - "@smithy/middleware-serde": "^4.0.3", - "@smithy/middleware-stack": "^4.0.2", "@smithy/node-config-provider": "^4.0.2", - "@smithy/node-http-handler": "^4.0.4", + "@smithy/property-provider": "^4.0.2", "@smithy/protocol-http": "^5.1.0", + "@smithy/signature-v4": "^5.1.0", "@smithy/smithy-client": "^4.2.1", "@smithy/types": "^4.2.0", - "@smithy/url-parser": "^4.0.2", - "@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.9", - "@smithy/util-defaults-mode-node": "^4.0.9", - "@smithy/util-endpoints": "^3.0.2", "@smithy/util-middleware": "^4.0.2", - "@smithy/util-retry": "^4.0.2", - "@smithy/util-utf8": "^4.0.0", + "fast-xml-parser": "4.4.1", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.775.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.775.0.tgz", - "integrity": "sha512-40iH3LJjrQS3LKUJAl7Wj0bln7RFPEvUYKFxtP8a+oKFDO0F65F52xZxIJbPn6sHkxWDAnZlGgdjZXM3p2g5wQ==", + "node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.798.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.798.0.tgz", + "integrity": "sha512-UvficjDO/Vrxd1xufR+5ey8NdDUrvIuiEWP/uu4kOkUTXk3IR89F+5UbYWSadhkysbyWN3tui09bWbIbq2Vhag==", "license": "Apache-2.0", "dependencies": { + "@aws-sdk/core": "3.798.0", "@aws-sdk/types": "3.775.0", + "@aws-sdk/util-arn-parser": "3.723.0", + "@smithy/core": "^3.3.0", "@smithy/node-config-provider": "^4.0.2", + "@smithy/protocol-http": "^5.1.0", + "@smithy/signature-v4": "^5.1.0", + "@smithy/smithy-client": "^4.2.1", "@smithy/types": "^4.2.0", "@smithy/util-config-provider": "^4.0.0", "@smithy/util-middleware": "^4.0.2", + "@smithy/util-stream": "^4.2.0", + "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, "engines": { @@ -884,23 +213,6 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/token-providers": { - "version": "3.798.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.798.0.tgz", - "integrity": "sha512-iYhNmHXfWLUwcMP9ldb/H+RMRLHZbBUWBgsoQqfb7sl6z24nH0qBJyL+oXHTCVBUYLP20CvUrVkcwlejDzyoRw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/nested-clients": "3.798.0", - "@aws-sdk/types": "3.775.0", - "@smithy/property-provider": "^4.0.2", - "@smithy/shared-ini-file-loader": "^4.0.2", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/types": { "version": "3.775.0", "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.775.0.tgz", @@ -926,21 +238,6 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/util-endpoints": { - "version": "3.787.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.787.0.tgz", - "integrity": "sha512-fd3zkiOkwnbdbN0Xp9TsP5SWrmv0SpT70YEdbb8wAj2DWQwiCmFszaSs+YCvhoCdmlR3Wl9Spu0pGpSAGKeYvQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.775.0", - "@smithy/types": "^4.2.0", - "@smithy/util-endpoints": "^3.0.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/util-format-url": { "version": "3.775.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.775.0.tgz", @@ -956,67 +253,6 @@ "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.775.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.775.0.tgz", - "integrity": "sha512-txw2wkiJmZKVdDbscK7VBK+u+TJnRtlUjRTLei+elZg2ADhpQxfVAQl436FUeIv6AhB/oRHW6/K/EAGXUSWi0A==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.775.0", - "@smithy/types": "^4.2.0", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.798.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.798.0.tgz", - "integrity": "sha512-yncgNd2inI+y5kdfn2i0oBwgCxwdtcVShNNVQ+5b/nuC1Lgjgcb+hmHAeTFMge7vhDP2Md8I+ih6bPMpK79lQQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/middleware-user-agent": "3.798.0", - "@aws-sdk/types": "3.775.0", - "@smithy/node-config-provider": "^4.0.2", - "@smithy/types": "^4.2.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.775.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.775.0.tgz", - "integrity": "sha512-b9NGO6FKJeLGYnV7Z1yvcP1TNU4dkD5jNsLWOF1/sygZoASaQhNOlaiJ/1OH331YQ1R1oWk38nBb0frsYkDsOQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@babel/code-frame": { "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", @@ -3125,241 +2361,54 @@ "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/@smithy/abort-controller": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.2.tgz", - "integrity": "sha512-Sl/78VDtgqKxN2+1qduaVE140XF+Xg+TafkncspwM4jFP/LHr76ZHmIY/y3V1M0mMLNk+Je6IGbzxy23RSToMw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.2.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.1.0", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.1.0.tgz", - "integrity": "sha512-8smPlwhga22pwl23fM5ew4T9vfLUCeFXlcqNOCD5M5h8VmNPNUE9j6bQSuRXpDSV11L/E/SwEBQuW8hr6+nS1A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.0.2", - "@smithy/types": "^4.2.0", - "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/core": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.3.0.tgz", - "integrity": "sha512-r6gvs5OfRq/w+9unPm7B3po4rmWaGh0CIL/OwHntGGux7+RhOOZLGuurbeMgWV6W55ZuyMTypJLeH0vn/ZRaWQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/middleware-serde": "^4.0.3", - "@smithy/protocol-http": "^5.1.0", - "@smithy/types": "^4.2.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-middleware": "^4.0.2", - "@smithy/util-stream": "^4.2.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/credential-provider-imds": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.2.tgz", - "integrity": "sha512-32lVig6jCaWBHnY+OEQ6e6Vnt5vDHaLiydGrwYMW9tPqO688hPGTYRamYJ1EptxEC2rAwJrHWmPoKRBl4iTa8w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.0.2", - "@smithy/property-provider": "^4.0.2", - "@smithy/types": "^4.2.0", - "@smithy/url-parser": "^4.0.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/eventstream-codec": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.0.2.tgz", - "integrity": "sha512-p+f2kLSK7ZrXVfskU/f5dzksKTewZk8pJLPvER3aFHPt76C2MxD9vNatSfLzzQSQB4FNO96RK4PSXfhD1TTeMQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/crc32": "5.2.0", - "@smithy/types": "^4.2.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.2", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.0.2.tgz", - "integrity": "sha512-CepZCDs2xgVUtH7ZZ7oDdZFH8e6Y2zOv8iiX6RhndH69nlojCALSKK+OXwZUgOtUZEUaZ5e1hULVCHYbCn7pug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/eventstream-serde-universal": "^4.0.2", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.1.0.tgz", - "integrity": "sha512-1PI+WPZ5TWXrfj3CIoKyUycYynYJgZjuQo8U+sphneOtjsgrttYybdqESFReQrdWJ+LKt6NEdbYzmmfDBmjX2A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-node": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.0.2.tgz", - "integrity": "sha512-C5bJ/C6x9ENPMx2cFOirspnF9ZsBVnBMtP6BdPl/qYSuUawdGQ34Lq0dMcf42QTjUZgWGbUIZnz6+zLxJlb9aw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/eventstream-serde-universal": "^4.0.2", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-universal": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.0.2.tgz", - "integrity": "sha512-St8h9JqzvnbB52FtckiHPN4U/cnXcarMniXRXTKn0r4b4XesZOGiAyUdj1aXbqqn1icSqBlzzUsCl6nPB018ng==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/eventstream-codec": "^4.0.2", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/fetch-http-handler": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.2.tgz", - "integrity": "sha512-+9Dz8sakS9pe7f2cBocpJXdeVjMopUDLgZs1yWeu7h++WqSbjUYv/JAJwKwXw1HV6gq1jyWjxuyn24E2GhoEcQ==", - "license": "Apache-2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@smithy/protocol-http": "^5.1.0", - "@smithy/querystring-builder": "^4.0.2", - "@smithy/types": "^4.2.0", - "@smithy/util-base64": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" + "type-detect": "4.0.8" } }, - "node_modules/@smithy/hash-blob-browser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.0.2.tgz", - "integrity": "sha512-3g188Z3DyhtzfBRxpZjU8R9PpOQuYsbNnyStc/ZVS+9nVX1f6XeNOa9IrAh35HwwIZg+XWk8bFVtNINVscBP+g==", - "license": "Apache-2.0", + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@smithy/chunked-blob-reader": "^5.0.0", - "@smithy/chunked-blob-reader-native": "^4.0.0", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" + "@sinonjs/commons": "^3.0.0" } }, - "node_modules/@smithy/hash-node": { + "node_modules/@smithy/abort-controller": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.2.tgz", - "integrity": "sha512-VnTpYPnRUE7yVhWozFdlxcYknv9UN7CeOqSrMH+V877v4oqtVYuoqhIhtSjmGPvYrYnAkaM61sLMKHvxL138yg==", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.2.tgz", + "integrity": "sha512-Sl/78VDtgqKxN2+1qduaVE140XF+Xg+TafkncspwM4jFP/LHr76ZHmIY/y3V1M0mMLNk+Je6IGbzxy23RSToMw==", "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.2.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.2", - "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.0.2.tgz", - "integrity": "sha512-POWDuTznzbIwlEXEvvXoPMS10y0WKXK790soe57tFRfvf4zBHyzE529HpZMqmDdwG9MfFflnyzndUQ8j78ZdSg==", + "node_modules/@smithy/core": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.3.0.tgz", + "integrity": "sha512-r6gvs5OfRq/w+9unPm7B3po4rmWaGh0CIL/OwHntGGux7+RhOOZLGuurbeMgWV6W55ZuyMTypJLeH0vn/ZRaWQ==", "license": "Apache-2.0", "dependencies": { + "@smithy/middleware-serde": "^4.0.3", + "@smithy/protocol-http": "^5.1.0", "@smithy/types": "^4.2.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-middleware": "^4.0.2", + "@smithy/util-stream": "^4.2.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -3367,13 +2416,16 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/invalid-dependency": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.2.tgz", - "integrity": "sha512-GatB4+2DTpgWPday+mnUkoumP54u/MDM/5u44KF9hIu8jF0uafZtQLcdfIKkIcUNuF/fBojpLEHZS/56JqPeXQ==", + "node_modules/@smithy/fetch-http-handler": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.2.tgz", + "integrity": "sha512-+9Dz8sakS9pe7f2cBocpJXdeVjMopUDLgZs1yWeu7h++WqSbjUYv/JAJwKwXw1HV6gq1jyWjxuyn24E2GhoEcQ==", "license": "Apache-2.0", "dependencies": { + "@smithy/protocol-http": "^5.1.0", + "@smithy/querystring-builder": "^4.0.2", "@smithy/types": "^4.2.0", + "@smithy/util-base64": "^4.0.0", "tslib": "^2.6.2" }, "engines": { @@ -3392,34 +2444,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/md5-js": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.0.2.tgz", - "integrity": "sha512-Hc0R8EiuVunUewCse2syVgA2AfSRco3LyAv07B/zCOMa+jpXI9ll+Q21Nc6FAlYPcpNcAXqBzMhNs1CD/pP2bA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.2.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.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.2.tgz", - "integrity": "sha512-hAfEXm1zU+ELvucxqQ7I8SszwQ4znWMbNv6PLMndN83JJN41EPuS93AIyh2N+gJ6x8QFhzSO6b7q2e6oClDI8A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/protocol-http": "^5.1.0", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/middleware-endpoint": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.1.tgz", @@ -3439,39 +2463,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/middleware-retry": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.1.tgz", - "integrity": "sha512-mBJOxn9aUYwcBUPQpKv9ifzrCn4EbhPUFguEZv3jB57YOMh0caS4P8HoLvUeNUI1nx4bIVH2SIbogbDfFI9DUA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.0.2", - "@smithy/protocol-http": "^5.1.0", - "@smithy/service-error-classification": "^4.0.2", - "@smithy/smithy-client": "^4.2.1", - "@smithy/types": "^4.2.0", - "@smithy/util-middleware": "^4.0.2", - "@smithy/util-retry": "^4.0.2", - "tslib": "^2.6.2", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-retry/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/@smithy/middleware-serde": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.3.tgz", @@ -3582,18 +2573,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/service-error-classification": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.2.tgz", - "integrity": "sha512-LA86xeFpTKn270Hbkixqs5n73S+LVM0/VZco8dqd+JT75Dyx3Lcw/MraL7ybjmz786+160K8rPOmhsq0SocoJQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.2.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/shared-ini-file-loader": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.2.tgz", @@ -3696,18 +2675,6 @@ "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", @@ -3733,54 +2700,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.9.tgz", - "integrity": "sha512-B8j0XsElvyhv6+5hlFf6vFV/uCSyLKcInpeXOGnOImX2mGXshE01RvPoGipTlRpIk53e6UfYj7WdDdgbVfXDZw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/property-provider": "^4.0.2", - "@smithy/smithy-client": "^4.2.1", - "@smithy/types": "^4.2.0", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.9.tgz", - "integrity": "sha512-wTDU8P/zdIf9DOpV5qm64HVgGRXvqjqB/fJZTEQbrz3s79JHM/E7XkMm/876Oq+ZLHJQgnXM9QHDo29dlM62eA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/config-resolver": "^4.1.0", - "@smithy/credential-provider-imds": "^4.0.2", - "@smithy/node-config-provider": "^4.0.2", - "@smithy/property-provider": "^4.0.2", - "@smithy/smithy-client": "^4.2.1", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-endpoints": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.2.tgz", - "integrity": "sha512-6QSutU5ZyrpNbnd51zRTL7goojlcnuOB55+F9VBD+j8JpRY50IGamsjlycrmpn8PQkmJucFW8A0LSfXj7jjtLQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.0.2", - "@smithy/types": "^4.2.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", @@ -3806,20 +2725,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/util-retry": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.2.tgz", - "integrity": "sha512-Qryc+QG+7BCpvjloFLQrmlSd0RsVRHejRXd78jNO3+oREueCjwG1CCEH1vduw/ZkM1U9TztwIKVIi3+8MJScGg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/service-error-classification": "^4.0.2", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/util-stream": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.0.tgz", @@ -3864,20 +2769,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/util-waiter": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.0.3.tgz", - "integrity": "sha512-JtaY3FxmD+te+KSI2FJuEcfNC9T/DGGVf551babM7fAaXhjJUt7oSYurH1Devxd2+BOSUACCgt3buinx4UnmEA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/abort-controller": "^4.0.2", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@sqltools/formatter": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", @@ -4869,12 +3760,6 @@ "node": ">= 6.0.0" } }, - "node_modules/append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", - "license": "MIT" - }, "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -4948,18 +3833,6 @@ "proxy-from-env": "^1.1.0" } }, - "node_modules/axios-retry": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.5.0.tgz", - "integrity": "sha512-aR99oXhpEDGo0UuAlYcn2iGRds30k366Zfa05XWScR9QaQD4JYiP3/1Qt1u7YlefUOK+cn0CcwoL1oefavQUlQ==", - "license": "Apache-2.0", - "dependencies": { - "is-retry-allowed": "^2.2.0" - }, - "peerDependencies": { - "axios": "0.x || 1.x" - } - }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -5086,20 +3959,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/backblaze-b2": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/backblaze-b2/-/backblaze-b2-1.7.1.tgz", - "integrity": "sha512-ns+oIO0NO5ysIIcs4xn2PfG34GlkGFLUckDWfQcsaCE2THDNRWzc5lWjR3LUrq6DA0E5KUGOhgkAs/q+QrgpNw==", - "license": "MIT", - "dependencies": { - "axios": "^1.9.0", - "axios-retry": "^4.5.0", - "lodash": "^4.17.21" - }, - "engines": { - "node": ">=10.0" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -5301,12 +4160,6 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "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": "2.0.2", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", @@ -5420,19 +4273,9 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, "license": "MIT" }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -5935,51 +4778,6 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "engines": [ - "node >= 0.8" - ], - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/concat-stream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/concat-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, - "node_modules/concat-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -6038,12 +4836,6 @@ "dev": true, "license": "MIT" }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "license": "MIT" - }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -8110,18 +6902,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-retry-allowed": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz", - "integrity": "sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -8134,12 +6914,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "license": "MIT" - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -9736,6 +8510,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "devOptional": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9883,36 +8658,6 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, - "node_modules/multer": { - "version": "1.4.5-lts.2", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.2.tgz", - "integrity": "sha512-VzGiVigcG9zUAoCNU+xShztrlr1auZOlurXynNvO9GiWD1/mTBbUljOKY+qMeazBqXgRnjzeEgJI/wyjJUHg9A==", - "license": "MIT", - "dependencies": { - "append-field": "^1.0.0", - "busboy": "^1.0.0", - "concat-stream": "^1.5.2", - "mkdirp": "^0.5.4", - "object-assign": "^4.1.1", - "type-is": "^1.6.4", - "xtend": "^4.0.0" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/multer/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "license": "MIT", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, "node_modules/napi-build-utils": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", @@ -10735,12 +9480,6 @@ } } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "license": "MIT" - }, "node_modules/promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", @@ -11973,14 +10712,6 @@ "ieee754": "^1.2.1" } }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -12805,12 +11536,6 @@ "node": ">= 0.6" } }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "license": "MIT" - }, "node_modules/typeorm": { "version": "0.3.21", "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.21.tgz", diff --git a/package.json b/package.json index fe84f03..a896734 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ "s3:setup": "ts-node src/utils/setup-s3-bucket.ts" }, "dependencies": { - "@aws-sdk/client-s3": "^3.798.0", "@aws-sdk/s3-request-presigner": "^3.798.0", "@prisma/client": "^6.4.1", "@stellar/stellar-sdk": "^13.3.0", @@ -32,7 +31,6 @@ "@types/swagger-ui-express": "^4.1.7", "@types/uuid": "^10.0.0", "axios": "^1.7.9", - "backblaze-b2": "^1.7.0", "bcryptjs": "^3.0.2", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", @@ -43,7 +41,6 @@ "express-rate-limit": "^7.5.0", "express-validator": "^7.2.0", "jsonwebtoken": "^9.0.2", - "multer": "^1.4.5-lts.2", "node-cron": "^3.0.3", "nodemailer": "^6.10.0", "pdf-lib": "^1.17.1", diff --git a/src/config/index.ts b/src/config/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/index.ts b/src/index.ts index e20d455..cea7322 100644 --- a/src/index.ts +++ b/src/index.ts @@ -186,13 +186,10 @@ prisma globalLogger.info("Cron jobs initialized successfully!"); app.listen(PORT, () => { - globalLogger.info( - `Server is running on http://localhost:${PORT}`, - { - port: PORT, - environment: ENV, - } - ); + globalLogger.info(`Server is running on http://localhost:${PORT}`, { + port: PORT, + environment: ENV, + }); if (ENV === "development") { globalLogger.info( diff --git a/src/modules/organization/presentation/controllers/organization.controller.ts b/src/modules/organization/presentation/controllers/organization.controller.ts index e306815..e1fc62c 100644 --- a/src/modules/organization/presentation/controllers/organization.controller.ts +++ b/src/modules/organization/presentation/controllers/organization.controller.ts @@ -8,10 +8,7 @@ import { GetAllOrganizationsUseCase } from "../../application/use-cases/get-all- import { CreateOrganizationDto } from "../dto/create-organization.dto"; import { UpdateOrganizationDto } from "../dto/update-organization.dto"; import { OrganizationNotFoundException } from "../../domain/exceptions/organization-not-found.exception"; -import { - UuidParamsDto, - PaginationQueryDto, -} from "../../../shared/dto/base.dto"; +import { PaginationQueryDto, UuidParamsDto } from "@/shared/dto/base.dto"; export class OrganizationController { constructor( @@ -40,7 +37,7 @@ export class OrganizationController { ); getOrganizationById = asyncHandler( - async (req: Request, res: Response): Promise => { + async (req: Request, res: Response): Promise => { const { id } = req.params; try { diff --git a/src/modules/photo/README.md b/src/modules/photo/README.md new file mode 100644 index 0000000..a9741a1 --- /dev/null +++ b/src/modules/photo/README.md @@ -0,0 +1,36 @@ +# ๐Ÿ“ธ Photos Module + +This module handles uploading, fetching, and deleting images. +Unlike other modules in the application, its architecture is slightly different, since file handling introduces particular requirements (e.g., Supabase Storage, Multer, public URLs). + +# ๐Ÿ”‘ Key Architectural Differences + +No use cases or repositories are used, only maintained Entity to get easy access on this information, but this Entity is generate for mi adapter, adapter interface required a return of PhotoEntity. +The flow is more direct: + +Controller โ†’ calls the Adapter for Supabase Storage and Prisma for persistence. + +Entity โ†’ ensures photo consistency (valid URL, userId, metadata). + +Dedicated Adapters: + +photo-service.adapter.interface.ts โ†’ defines the generic interface for a storage service. + +supabase-service.adapter.ts โ†’ concrete implementation using Supabase Storage. + +Simplified Controllers: +Controllers use asyncHandler, validators, and Multer for file processing. + +# ๐Ÿ“‚ Structure + +```text +modules/ + photo/ + domain/entities/interfaces/ #interfaces of entity + domain/entitites/photo.entity.ts #Entity + infrastructure/ + presentation/controllers/ + presentation/dto + routes.ts +README.md +``` diff --git a/src/modules/photo/domain/entities/interfaces/photo.interface.ts b/src/modules/photo/domain/entities/interfaces/photo.interface.ts new file mode 100644 index 0000000..ab53da3 --- /dev/null +++ b/src/modules/photo/domain/entities/interfaces/photo.interface.ts @@ -0,0 +1,49 @@ +export interface IStorageAdapter { + upload(file: Buffer, filename: string): Promise<{ url: string; key: string }>; + delete(key: string): Promise; +} + +export interface IPhotoMetadata { + fileSize?: number; + mimeType?: string; + dimensions?: { + width: number; + height: number; + }; + camera?: { + make?: string; + model?: string; + settings?: { + iso?: number; + aperture?: string; + shutterSpeed?: string; + }; + }; + location?: { + latitude?: number; + longitude?: number; + address?: string; + }; + tags?: string[]; + description?: string; + [key: string]: unknown; // Allow additional properties +} + +export interface IPhotoProps { + id?: string; + url: string; + userId: string; + uploadedAt?: Date; + metadata?: IPhotoMetadata; +} + +export interface IPhoto { + id: string; + url: string; + userId: string; + uploadedAt: Date; + metadata?: IPhotoMetadata; + validate(): boolean; + updateMetadata(newMetadata: Partial): void; + toObject(): IPhotoProps; +} diff --git a/src/modules/photo/domain/entities/photo.entity.ts b/src/modules/photo/domain/entities/photo.entity.ts index f8a3693..1180a09 100644 --- a/src/modules/photo/domain/entities/photo.entity.ts +++ b/src/modules/photo/domain/entities/photo.entity.ts @@ -1,44 +1,36 @@ -import { Entity, Column } from "typeorm"; import { BaseEntity } from "../../../shared/domain/entities/base.entity"; +import { IPhotoMetadata, IPhotoProps } from "./interfaces/photo.interface"; +import { + InvalidPhotoUrlException, + MissingUserIdException, +} from "../exceptions/domain.exception"; -export interface PhotoProps { - id?: string; - url: string; - userId: string; - uploadedAt?: Date; - metadata?: Record; -} - -@Entity("photos") -export class Photo extends BaseEntity { - @Column({ type: "varchar", length: 500, nullable: false }) +export class PhotoEntity extends BaseEntity { url: string; - @Column({ type: "uuid", nullable: false }) userId: string; - @Column({ type: "jsonb", nullable: true }) - metadata?: Record; + metadata?: IPhotoMetadata; // Domain logic and validation - public validate(): boolean { + protected validate(): boolean { if (!this.url || this.url.trim() === "") { - throw new Error("Photo URL is required"); + throw new InvalidPhotoUrlException(this.url); } if (!/^https?:\/\/.+$/.test(this.url)) { - throw new Error("Photo URL must be a valid HTTP/HTTPS URL"); + throw new InvalidPhotoUrlException(this.url); } if (!this.userId || this.userId.trim() === "") { - throw new Error("User ID is required"); + throw new MissingUserIdException(); } return true; } // Update metadata - public updateMetadata(newMetadata: Record): void { + public updateMetadata(newMetadata: IPhotoMetadata): void { this.metadata = { ...this.metadata, ...newMetadata, @@ -46,8 +38,8 @@ export class Photo extends BaseEntity { } // Static factory method - public static create(props: PhotoProps): Photo { - const photo = new Photo(); + public static create(props: IPhotoProps): PhotoEntity { + const photo = new PhotoEntity(); photo.url = props.url; photo.userId = props.userId; photo.metadata = props.metadata ?? {}; @@ -56,7 +48,7 @@ export class Photo extends BaseEntity { } // Convert to plain object for persistence - public toObject(): PhotoProps { + public toObject(): IPhotoProps { return { id: this.id, url: this.url, diff --git a/src/modules/photo/domain/exceptions/domain.exception.ts b/src/modules/photo/domain/exceptions/domain.exception.ts new file mode 100644 index 0000000..4faa74f --- /dev/null +++ b/src/modules/photo/domain/exceptions/domain.exception.ts @@ -0,0 +1,13 @@ +import { DomainException } from "../../../shared/domain/exceptions/domain.exception"; + +export class InvalidPhotoUrlException extends DomainException { + constructor(url: string) { + super(`Invalid photo URL: ${url}`); + } +} + +export class MissingUserIdException extends DomainException { + constructor() { + super("User ID is required"); + } +} diff --git a/src/modules/photo/entities/photo.entity.ts b/src/modules/photo/entities/photo.entity.ts deleted file mode 100644 index 5de9c11..0000000 --- a/src/modules/photo/entities/photo.entity.ts +++ /dev/null @@ -1,2 +0,0 @@ -// Re-export the domain entity -export { Photo, PhotoProps } from "../domain/entities/photo.entity"; diff --git a/src/modules/photo/infrastructure/adapters/interface/photo-service.adapter.ts b/src/modules/photo/infrastructure/adapters/interface/photo-service.adapter.ts new file mode 100644 index 0000000..df7bf02 --- /dev/null +++ b/src/modules/photo/infrastructure/adapters/interface/photo-service.adapter.ts @@ -0,0 +1,16 @@ +import { IPhotoMetadata } from "@/modules/photo/domain/entities/interfaces/photo.interface"; +import { PhotoEntity } from "@/modules/photo/domain/entities/photo.entity"; + +export interface IPhotoServiceAdapter { + upload( + file: Express.Multer.File, + userId: string, + metadata?: IPhotoMetadata + ): Promise; + getById(photoId: string): Promise<{ id: string; url: string } | null>; + delete(photoUrl: string): Promise; + updateMetadata( + photoId: string, + metadata: IPhotoMetadata + ): Promise; +} diff --git a/src/modules/photo/infrastructure/adapters/supabase-service.adapter.ts b/src/modules/photo/infrastructure/adapters/supabase-service.adapter.ts new file mode 100644 index 0000000..39062ed --- /dev/null +++ b/src/modules/photo/infrastructure/adapters/supabase-service.adapter.ts @@ -0,0 +1,105 @@ +import { prisma } from "@/config/prisma"; +import { IPhotoMetadata } from "../../domain/entities/interfaces/photo.interface"; +import { IPhotoServiceAdapter } from "./interface/photo-service.adapter"; +import { supabase } from "@/config/supabase"; +import { PhotoEntity } from "../../domain/entities/photo.entity"; + +export class SupabasePhotoService implements IPhotoServiceAdapter { + //Metadata options are enabled if needed later + async upload( + file: Express.Multer.File, + userId: string, + metadata?: IPhotoMetadata + ): Promise { + const fileName = `${Date.now()}-${file.originalname}`; + + // Subir archivo a Supabase Storage + const { error: uploadError } = await supabase.storage + .from("photos") + .upload(fileName, file.buffer, { + contentType: file.mimetype, + upsert: false, + }); + + if (uploadError) throw uploadError; + + // Obtener URL pรบblica + const { data: publicUrl } = supabase.storage + .from("photos") + .getPublicUrl(fileName); + + if (!publicUrl) throw new Error("Could not get public URL"); + + // Guardar en DB con Prisma + const photo = await prisma.photo.create({ + data: { + userId, + url: publicUrl.publicUrl, + metadata: { + ...metadata, + fileName: file.originalname, + fileSize: file.size, + mimeType: file.mimetype, + }, + uploadedAt: new Date(), + }, + }); + + return PhotoEntity.create({ + id: photo.url, + url: photo.url, + userId, + metadata, + uploadedAt: photo.uploadedAt ?? new Date(), + }); + } + + async delete(photoId: string): Promise { + // Find in DB + const photo = await prisma.photo.findUnique({ + where: { id: photoId }, + }); + + if (!photo) { + throw new Error("Photo not found"); + } + + // Extract fileName from public URL (what follows after /photos/) + const urlParts = photo.url.split("/"); + const fileName = urlParts[urlParts.length - 1]; + + // Delete from Supabase Storage using supabaseStorage + const { error: deleteError } = await supabase.storage + .from("photos") + .remove([fileName]); + + if (deleteError) throw deleteError; + + // Delete from DB + await prisma.photo.delete({ where: { id: photoId } }); + } + + async getById(photoId: string): Promise<{ id: string; url: string } | null> { + const photo = await prisma.photo.findUnique({ + where: { id: photoId }, + }); + + if (!photo) return null; + + return { id: photo.id, url: photo.url }; + } + + async updateMetadata( + photoId: string, + metadata: IPhotoMetadata + ): Promise { + const updatedPhoto = await prisma.photo.update({ + where: { id: photoId }, + data: { metadata }, + select: { metadata: true }, + }); + + // Assuming metadata is not null after update + return updatedPhoto.metadata as IPhotoMetadata; + } +} diff --git a/src/modules/photo/infrastructure/services/BackblazeService.ts b/src/modules/photo/infrastructure/services/BackblazeService.ts deleted file mode 100644 index a197fc7..0000000 --- a/src/modules/photo/infrastructure/services/BackblazeService.ts +++ /dev/null @@ -1,45 +0,0 @@ -import B2 from "backblaze-b2"; -import fs from "fs"; - -export class BackblazeService { - private b2: B2; - - constructor() { - this.b2 = new B2({ - applicationKeyId: process.env.BACKBLAZE_APPLICATION_KEY_ID!, - applicationKey: process.env.BACKBLAZE_APPLICATION_KEY!, - }); - } - - async authorize() { - await this.b2.authorize(); - } - - async uploadFile(filePath: string, fileName: string): Promise { - await this.authorize(); - - const { data } = await this.b2.getUploadUrl({ - bucketId: process.env.BACKBLAZE_BUCKET_ID!, - }); - - const buffer = fs.readFileSync(filePath); - - const upload = await this.b2.uploadFile({ - uploadUrl: data.uploadUrl, - uploadAuthToken: data.authorizationToken, - fileName, - data: buffer, - }); - - return upload.data.fileId; - } - - async deleteFile(fileId: string, fileName: string): Promise { - await this.authorize(); - - await this.b2.deleteFileVersion({ - fileId, - fileName, - }); - } -} diff --git a/src/modules/photo/interfaces/photo.interface.ts b/src/modules/photo/interfaces/photo.interface.ts deleted file mode 100644 index 2c4fd74..0000000 --- a/src/modules/photo/interfaces/photo.interface.ts +++ /dev/null @@ -1,19 +0,0 @@ -export interface IPhotoProps { - id?: string; - url: string; - userId: string; - uploadedAt?: Date; - metadata?: Record; -} - -export interface IPhoto { - id: string; - url: string; - userId: string; - uploadedAt: Date; - metadata?: Record; - - validate(): boolean; - updateMetadata(newMetadata: Record): void; - toObject(): IPhotoProps; -} diff --git a/src/modules/photo/presentation/controllers/PhotoController.ts b/src/modules/photo/presentation/controllers/PhotoController.ts deleted file mode 100644 index df20197..0000000 --- a/src/modules/photo/presentation/controllers/PhotoController.ts +++ /dev/null @@ -1,84 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable @typescript-eslint/no-unused-vars */ -import { Request, Response, Router, NextFunction } from "express"; -import multer from "multer"; -import { PrismaClient } from "@prisma/client"; -import { body, param, validationResult } from "express-validator"; -import path from "path"; - -// Extend the Request interface to include the 'file' property -interface MulterRequest extends Request { - file?: Express.Multer.File; -} - -const prisma = new PrismaClient(); -const router = Router(); -const upload = multer({ dest: "uploads/" }); - -// Middleware for handling validation errors -const validate = - ( - validations: { - run: ( - req: Request - ) => Promise<{ isEmpty: () => boolean; array: () => any[] }>; - }[] - ) => - async (req: Request, res: Response, next: NextFunction): Promise => { - for (const validation of validations) { - const result = await validation.run(req); - if (!result.isEmpty()) { - res.status(400).json({ errors: result.array() }); - return; - } - } - next(); - }; - -router.post( - "/upload", - upload.single("photo"), - validate([body("userId").isInt().withMessage("userId must be an integer")]), - async (req: MulterRequest, res: Response): Promise => { - try { - if (!req.file) { - res.status(400).json({ error: "Photo is required" }); - return; - } - const { userId } = req.body; - const photo = await prisma.photo.create({ - data: { - userId: parseInt(userId, 10).toString(), - uploadedAt: req.file.path, - url: req.file.path, // Assuming the file path is used as the URL - }, - }); - res.status(201).json(photo); - } catch (error) { - res.status(500).json({ error: "Internal Server Error" }); - } - } -); - -// Get photo by ID -router.get( - "/:id", - validate([param("id").isInt().withMessage("Photo ID must be an integer")]), - async (req: Request, res: Response): Promise => { - try { - const { id } = req.params; - const photo = await prisma.photo.findUnique({ where: { id } }); - - if (!photo) { - res.status(404).json({ error: "Photo not found" }); - return; - } - - res.json(photo); - } catch (error) { - res.status(500).json({ error: "Internal Server Error" }); - } - } -); - -export default router; diff --git a/src/modules/photo/presentation/controllers/photo-controller.ts b/src/modules/photo/presentation/controllers/photo-controller.ts new file mode 100644 index 0000000..fcfcb42 --- /dev/null +++ b/src/modules/photo/presentation/controllers/photo-controller.ts @@ -0,0 +1,106 @@ +import { Request, Response } from "express"; +import { asyncHandler } from "@/utils/asyncHandler"; +import { SupabasePhotoService } from "../../infrastructure/adapters/supabase-service.adapter"; + +// Extend the Request interface to include the 'file' property +interface MulterRequest extends Request { + file?: Express.Multer.File; +} + +export class PhotoController { + constructor(private readonly supabasePhotoService: SupabasePhotoService) {} + + uploadPhoto = asyncHandler( + async (req: MulterRequest, res: Response): Promise => { + if (!req.file) { + res.status(400).json({ error: "Photo is required" }); + return; + } + + const { userId } = req.body; + + if (!userId) { + res.status(400).json({ error: "User ID is required" }); + return; + } + + const photo = await this.supabasePhotoService.upload(req.file, userId); + res.status(201).json(photo); + } + ); + + deletePhoto = asyncHandler( + async (req: Request, res: Response): Promise => { + const { id } = req.params; + + // Verificar si la foto existe usando el servicio + const photo = await this.supabasePhotoService.getById(id); + + if (!photo) { + res.status(404).json({ error: "Photo not found" }); + return; + } + + // Eliminar la foto usando el servicio + await this.supabasePhotoService.delete(id); + res.status(204).send(); // No content + } + ); + + getPhotoById = asyncHandler( + async (req: Request, res: Response): Promise => { + const { id } = req.params; + + const photo = await this.supabasePhotoService.getById(id); + + if (!photo) { + res.status(404).json({ error: "Photo not found" }); + return; + } + + res.json(photo); + } + ); + + updatePhoto = asyncHandler( + async (req: Request, res: Response): Promise => { + const { id } = req.params; + const updateData = req.body; + + // Verificar si la foto existe + const existingPhoto = await this.supabasePhotoService.getById(id); + + if (!existingPhoto) { + res.status(404).json({ error: "Photo not found" }); + return; + } + + const updatedPhoto = await this.supabasePhotoService.upload( + updateData, + id + ); + res.json(updatedPhoto); + } + ); + + updatePhotoMetadata = asyncHandler( + async (req: Request, res: Response): Promise => { + const { id } = req.params; + const { metadata } = req.body; + + // Verificar si la foto existe + const existingPhoto = await this.supabasePhotoService.getById(id); + + if (!existingPhoto) { + res.status(404).json({ error: "Photo not found" }); + return; + } + + const updatedPhoto = await this.supabasePhotoService.updateMetadata( + id, + metadata + ); + res.json(updatedPhoto); + } + ); +} diff --git a/src/modules/photo/presentation/dto/delete-photo.dto.ts b/src/modules/photo/presentation/dto/delete-photo.dto.ts new file mode 100644 index 0000000..9f6517d --- /dev/null +++ b/src/modules/photo/presentation/dto/delete-photo.dto.ts @@ -0,0 +1,6 @@ +import { IsInt } from "class-validator"; + +export class DeletePhotoDto { + @IsInt({ message: "Photo ID must be an integer" }) + id!: number; +} diff --git a/src/modules/photo/presentation/dto/get-photo.dto.ts b/src/modules/photo/presentation/dto/get-photo.dto.ts new file mode 100644 index 0000000..e11f397 --- /dev/null +++ b/src/modules/photo/presentation/dto/get-photo.dto.ts @@ -0,0 +1,6 @@ +import { IsInt } from "class-validator"; + +export class GetPhotoDto { + @IsInt({ message: "Photo ID must be an integer" }) + id!: number; +} diff --git a/src/modules/photo/presentation/dto/index.ts b/src/modules/photo/presentation/dto/index.ts new file mode 100644 index 0000000..ea67d02 --- /dev/null +++ b/src/modules/photo/presentation/dto/index.ts @@ -0,0 +1,3 @@ +export { DeletePhotoDto } from "./delete-photo.dto"; +export { GetPhotoDto } from "./get-photo.dto"; +export { UploadPhotoDto } from "./upload-photo.dto"; diff --git a/src/modules/photo/presentation/dto/upload-photo.dto.ts b/src/modules/photo/presentation/dto/upload-photo.dto.ts new file mode 100644 index 0000000..a1d1bd8 --- /dev/null +++ b/src/modules/photo/presentation/dto/upload-photo.dto.ts @@ -0,0 +1,6 @@ +import { IsInt } from "class-validator"; + +export class UploadPhotoDto { + @IsInt({ message: "userId must be an integer" }) + userId!: number; +} diff --git a/src/modules/photo/presentation/routes.ts b/src/modules/photo/presentation/routes.ts new file mode 100644 index 0000000..ae1ddc1 --- /dev/null +++ b/src/modules/photo/presentation/routes.ts @@ -0,0 +1,25 @@ +import { Router } from "express"; +import multer from "multer"; +import { PhotoController } from "./controllers/photo-controller"; +import { validateDto } from "@/shared/middleware/validation.middleware"; +import { DeletePhotoDto, GetPhotoDto, UploadPhotoDto } from "./dto"; +import { SupabasePhotoService } from "../infrastructure/adapters/supabase-service.adapter"; + +const router = Router(); +const upload = multer({ dest: "uploads/" }); +const service = new SupabasePhotoService(); +const photoController = new PhotoController(service); + +// Middleware for handling validation errors +router.post( + "/upload", + upload.single("photo"), + validateDto(UploadPhotoDto), + photoController.uploadPhoto +); + +router.delete("/:id", validateDto(DeletePhotoDto), photoController.deletePhoto); + +router.get("/:id", validateDto(GetPhotoDto), photoController.getPhotoById); + +export default router; diff --git a/src/repository/IPhotoRepository.ts b/src/repository/IPhotoRepository.ts deleted file mode 100644 index 061fd4b..0000000 --- a/src/repository/IPhotoRepository.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Photo } from "../modules/photo/domain/entities/photo.entity"; - -export interface IPhotoRepository { - findById(id: string): Promise; - findAll(): Promise; - create(data: Partial): Promise; - update(id: string, data: Partial): Promise; - delete(id: string): Promise; -} diff --git a/src/repository/PhotoRepository.ts b/src/repository/PhotoRepository.ts deleted file mode 100644 index 75a6ad5..0000000 --- a/src/repository/PhotoRepository.ts +++ /dev/null @@ -1,86 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { PrismaClient } from "@prisma/client"; -import { IPhotoRepository } from "./IPhotoRepository"; -import { Photo } from "../modules/photo/domain/entities/photo.entity"; - -// Define our own types based on the Prisma schema -interface PrismaPhoto { - id: string; - url: string; - userId: string; - uploadedAt: Date; - metadata: any; -} - -const prisma = new PrismaClient(); - -export class PhotoRepository implements IPhotoRepository { - async findById(id: string): Promise { - const record = (await prisma.photo.findUnique({ - where: { id }, - })) as unknown as PrismaPhoto | null; - return record ? Photo.create({ - id: record.id, - url: record.url, - userId: record.userId, - uploadedAt: record.uploadedAt, - metadata: record.metadata - }) : null; - } - - async findAll(): Promise { - const records = (await prisma.photo.findMany()) as unknown as PrismaPhoto[]; - return records.map((r) => Photo.create({ - id: r.id, - url: r.url, - userId: r.userId, - uploadedAt: r.uploadedAt, - metadata: r.metadata - })); - } - - async create(data: Partial): Promise { - const photo = Photo.create({ - url: data.url!, - userId: data.userId!, - uploadedAt: new Date(), - metadata: data.metadata || {}, - }); - const created = (await prisma.photo.create({ - data: { - url: photo.url, - userId: photo.userId, - metadata: photo.metadata || {}, - }, - })) as unknown as PrismaPhoto; - return Photo.create({ - id: created.id, - url: created.url, - userId: created.userId, - uploadedAt: created.uploadedAt, - metadata: created.metadata - }); - } - - async update(id: string, data: Partial): Promise { - const updated = (await prisma.photo.update({ - where: { id }, - data: { - url: data.url, - userId: data.userId, - metadata: data.metadata, - }, - })) as unknown as PrismaPhoto; - return Photo.create({ - id: updated.id, - url: updated.url, - userId: updated.userId, - uploadedAt: updated.uploadedAt, - metadata: updated.metadata - }); - } - - async delete(id: string): Promise { - await prisma.photo.delete({ where: { id } }); - } -} diff --git a/src/shared/middleware/validation.middleware.ts b/src/shared/middleware/validation.middleware.ts index 54fb7cc..17243c3 100644 --- a/src/shared/middleware/validation.middleware.ts +++ b/src/shared/middleware/validation.middleware.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { validate, ValidationError } from "class-validator"; -import { plainToClass } from "class-transformer"; +import { plainToInstance } from "class-transformer"; export interface ValidationErrorResponse { success: false; @@ -19,7 +19,7 @@ export function validateDto(dtoClass: new () => T) { next: NextFunction ): Promise => { try { - const dto = plainToClass(dtoClass, req.body); + const dto = plainToInstance(dtoClass, req.body); const errors = await validate(dto); if (errors.length > 0) { @@ -57,7 +57,7 @@ export function validateQueryDto(dtoClass: new () => T) { next: NextFunction ): Promise => { try { - const dto = plainToClass(dtoClass, req.query); + const dto = plainToInstance(dtoClass, req.query); const errors = await validate(dto); if (errors.length > 0) { @@ -77,7 +77,9 @@ export function validateQueryDto(dtoClass: new () => T) { return; } - req.query = dto as Record; + Object.keys(req.query).forEach((key) => delete req.query[key]); + Object.assign(req.query, dto); + next(); } catch { res.status(500).json({ @@ -95,7 +97,7 @@ export function validateParamsDto(dtoClass: new () => T) { next: NextFunction ): Promise => { try { - const dto = plainToClass(dtoClass, req.params); + const dto = plainToInstance(dtoClass, req.params); const errors = await validate(dto); if (errors.length > 0) {