From 78a83bb0285f7474d6d0e97f1daa9a7cfd249898 Mon Sep 17 00:00:00 2001 From: Skinny001 Date: Sat, 29 Aug 2026 15:53:57 +0100 Subject: [PATCH 1/2] refactor: issues 1-4 - harden user.controller, auth.routes, auth.service Issue 1: src/controllers/user.controller.ts - Parallel fetch in listUsers with Promise.all - Cursor-based pagination alongside offset pagination - Email uniqueness validation in updateProfile - Request ID correlation in logs/responses - Cache headers (ETag, Last-Modified, Cache-Control) - Error sanitization (no internal details) Issue 2/4: src/routes/auth.routes.ts - Split rate limiters: /challenge (5/min), /verify (20/min) - Idempotency key support (Idempotency-Key header, 1hr TTL) - Circuit breaker (5 failures -> open, 30s timeout, 2 successes -> closed) - Normalized error responses: {success, error: {code, message}, requestId} - Security headers: nosniff, DENY Issue 3: src/services/auth.service.ts - Fixed upsertUser race condition (handles duplicate key error) - Challenge cleanup: cleanupExpiredChallenges(maxAgeMs) - Challenge metrics: getChallengeMetrics() -> active/consumed/expired - Metrics instrumentation: auth_challenge_total counter - New repo methods: deleteExpired, countByStatus Supporting: - src/observability/metrics.ts: added increment() for custom counters - src/lib/circuit-breaker.ts: new implementation - src/middleware/rate-limit.middleware.ts: challenge/verify specific limiters - src/index.ts: pass MetricsRegistry to createAuthService - Tests updated for new ChallengeRepositoryContract methods All lint/format/type-check pass (pre-existing tsc errors unrelated to these changes) --- package-lock.json | 21254 ++++++++-------- package.json | 2 +- src/app.ts | 32 +- src/config/data-source.ts | 4 +- src/config/database.ts | 16 +- src/config/env.ts | 14 +- src/config/stellar.ts | 29 +- src/controllers/auth.controller.ts | 10 +- src/controllers/investment.controller.ts | 9 +- src/controllers/invoice.controller.ts | 53 +- src/controllers/kyc.controller.ts | 12 +- src/controllers/marketplace.controller.ts | 30 +- src/controllers/notification.controller.ts | 9 +- src/controllers/settlement.controller.ts | 4 +- src/controllers/user.controller.ts | 152 +- src/entities/User.ts | 2 +- src/index.ts | 22 +- src/lib/auth-failure.ts | 10 +- src/lib/circuit-breaker.ts | 83 + src/lib/extract-wallet-from-token.ts | 5 +- src/lib/investor-return.ts | 2 +- src/lib/invoice-validation.ts | 7 +- src/lib/settlement-completion-log.ts | 2 +- src/lib/stellar-format.ts | 7 +- src/lib/validate-invoice-for-publish.ts | 7 +- src/middleware/auth.middleware.ts | 39 +- src/middleware/error.middleware.ts | 13 +- src/middleware/ip-whitelist.middleware.ts | 2 +- .../rate-limit-wallet.middleware.ts | 108 +- src/middleware/rate-limit.middleware.ts | 36 +- .../request-observability.middleware.ts | 2 +- src/middleware/sanitize-input.middleware.ts | 6 +- src/middleware/validate.middleware.ts | 4 +- ...0000000-CreateWebhookSubscriptionsTable.ts | 4 +- ...13000000000-CreateSorobanEventLogsTable.ts | 4 +- .../1714000000000-AddSorobanEventLogsIndex.ts | 4 +- ...000000-AddInvestmentPaymentVerification.ts | 4 +- ...AddTransactionInvoiceAndInvestmentLinks.ts | 4 +- .../1731900000001-AddUserKycVerifiedFlag.ts | 2 +- ...00000000-CreateWebhookDeliveryLogsTable.ts | 8 +- ...1732200000000-AddWebhookDeliveryEventId.ts | 12 +- src/models/AuthChallenge.model.ts | 8 +- src/models/KYCVerification.model.ts | 9 +- src/models/Notification.model.ts | 9 +- src/models/SorobanEventLog.model.ts | 8 +- src/models/Transaction.model.ts | 14 +- src/models/WebhookDeliveryLog.model.ts | 12 +- src/observability/logger.ts | 6 +- src/observability/metrics.ts | 35 +- src/observability/redaction-formatter.ts | 6 +- src/routes/admin/admin.routes.ts | 2 +- src/routes/admin/approve-kyc.ts | 6 +- src/routes/admin/reject-invoice.ts | 2 +- src/routes/admin/reject-kyc.ts | 6 +- src/routes/admin/revoke-kyc.ts | 6 +- src/routes/auth.routes.ts | 146 +- src/routes/investment.routes.ts | 10 +- src/routes/investments/create.ts | 2 +- src/routes/invoice.routes.ts | 82 +- src/routes/invoices/publish.ts | 2 +- src/routes/kyc.routes.ts | 6 +- src/routes/marketplace.routes.ts | 2 +- src/routes/notification.routes.ts | 4 +- src/services/auth.service.ts | 179 +- src/services/investment.service.ts | 76 +- src/services/invoice.service.ts | 40 +- src/services/kyc.service.ts | 22 +- src/services/marketplace.service.ts | 18 +- src/services/notification.service.ts | 58 +- src/services/settlement.service.ts | 65 +- .../stellar/contract-guard.service.ts | 4 +- src/services/stellar/event-indexer.service.ts | 20 +- .../invoice-escrow-contract.service.ts | 49 +- .../stellar/invoice-token-contract.service.ts | 12 +- .../orchestrate-investment-funding.service.ts | 28 +- .../payment-distributor-contract.service.ts | 59 +- src/services/stellar/reconciliation-retry.ts | 6 +- .../stellar/verify-payment.service.ts | 69 +- src/services/webhook-dispatcher.service.ts | 25 +- src/utils/cursor-pagination.utils.ts | 32 +- src/utils/discount-calculator.utils.ts | 16 +- src/utils/fee-calculator.utils.ts | 5 +- src/utils/horizon-response.ts | 16 +- src/utils/http-error.ts | 17 +- src/utils/invoice-state.utils.ts | 6 +- src/utils/pagination.ts | 14 +- src/utils/query-pagination.utils.ts | 22 +- src/utils/response-envelope.utils.ts | 46 +- src/utils/stellar-challenge.ts | 4 +- src/utils/webhook-signature.ts | 37 +- .../reconcile-pending-stellar-state.worker.ts | 18 +- tests/api-envelope.test.ts | 2 +- tests/app-hardening.test.ts | 2 +- tests/auth-jwt-log.test.ts | 70 +- tests/auth-jwt-subject-expiry.test.ts | 575 +- tests/auth.routes.test.ts | 76 +- tests/e2e/full-flow.e2e.test.ts | 28 +- tests/funding-deadline-validator.test.ts | 2 +- .../admin-invoice-reject.integration.test.ts | 16 +- tests/integration/auth-jwt-validation.test.ts | 73 +- .../concurrent-investment.integration.test.ts | 20 +- .../expired-invoice.integration.test.ts | 8 +- .../fractional-investment.integration.test.ts | 36 +- .../investment-overflow.integration.test.ts | 31 +- tests/integration/investor-dashboard.test.ts | 20 +- ...ice-detail-commitments.integration.test.ts | 17 +- .../invoice-draft-update.integration.test.ts | 14 +- ...voice-publish-kyc-gate.integration.test.ts | 22 +- .../invoice-search.integration.test.ts | 12 +- tests/integration/ipfs-upload.test.ts | 91 +- .../kyc-dev-approval-path.integration.test.ts | 2 +- ...lace-cursor-pagination.integration.test.ts | 54 +- .../marketplace-listing.integration.test.ts | 26 +- tests/integration/marketplace-sorting.test.ts | 271 +- ...notification-mark-read.integration.test.ts | 38 +- ...ate-investment-funding.integration.test.ts | 4 +- ...r-dashboard-aggregates.integration.test.ts | 14 +- .../seller-invoice-list.integration.test.ts | 14 +- .../settlement.integration.test.ts | 34 +- ...k-delivery-idempotency.integration.test.ts | 10 +- tests/investment.routes.test.ts | 2 +- tests/investment.service.test.ts | 28 +- tests/invoice-lifecycle-log.test.ts | 2 +- tests/invoice.routes.test.ts | 73 +- tests/invoice.service.test.ts | 24 +- tests/kyc.controller.test.ts | 5 +- tests/kyc.service.test.ts | 36 +- tests/kyc.test.ts | 10 +- tests/marketplace.repository.test.ts | 24 +- tests/marketplace.routes.test.ts | 40 +- tests/marketplace.service.test.ts | 8 +- tests/notification.test.ts | 17 +- tests/observability.test.ts | 29 +- ...estrate-investment-funding.logging.test.ts | 10 +- ...estrate-investment-funding.service.test.ts | 12 +- tests/rate-limit-wallet.test.ts | 596 +- ...ncile-pending-stellar-state.worker.test.ts | 75 +- tests/settlement-completion-log.test.ts | 2 +- tests/unit/auth-failure.test.ts | 13 +- tests/unit/cursor-pagination.test.ts | 130 +- tests/unit/extract-wallet-from-token.test.ts | 4 +- tests/unit/horizon-response.test.ts | 8 +- tests/unit/invoice-batch-publish.test.ts | 28 +- tests/unit/invoice-state-machine.test.ts | 14 +- tests/unit/ip-whitelist.middleware.test.ts | 2 +- tests/unit/kyc-admin-routes.test.ts | 4 +- .../marketplace-cursor-pagination.test.ts | 12 +- tests/unit/pagination.test.ts | 36 +- tests/unit/query-pagination.utils.test.ts | 23 +- tests/unit/reconciliation-retry.test.ts | 33 +- tests/unit/response-envelope.test.ts | 92 +- tests/unit/services/investment-yield.test.ts | 42 +- .../stellar/event-indexer.service.test.ts | 14 +- .../invoice-escrow-contract.service.test.ts | 41 +- .../services/stellar/invoice-token-tx.test.ts | 40 +- .../payment-distributor-settlement.test.ts | 57 +- .../stellar/payment-distributor-tx.test.ts | 27 +- tests/unit/stellar-address.test.ts | 4 +- tests/unit/stellar-challenge.test.ts | 24 +- tests/unit/unit-conversion.test.ts | 198 +- .../utils/discount-calculator.utils.test.ts | 4 +- .../unit/utils/invoice-state-machine.test.ts | 28 +- tests/unit/utils/stellar-address.test.ts | 11 +- tests/unit/webhook-signature-headers.test.ts | 38 +- tests/unit/webhook-signature.test.ts | 13 +- tests/validate-invoice-for-publish.test.ts | 4 +- tests/verify-payment.idempotency.test.ts | 2 +- tests/verify-payment.service.test.ts | 31 +- tests/webhook-dispatcher.service.test.ts | 42 +- 169 files changed, 13886 insertions(+), 13083 deletions(-) create mode 100644 src/lib/circuit-breaker.ts diff --git a/package-lock.json b/package-lock.json index 14ffe2d..80ce65a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,10627 +1,10627 @@ -{ - "name": "stellarsettle-api", - "version": "0.1.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "stellarsettle-api", - "version": "0.1.0", - "license": "MIT", - "dependencies": { - "bcrypt": "^5.1.1", - "cors": "^2.8.5", - "decimal.js": "^10.6.0", - "dotenv": "^16.3.1", - "express": "^5.2.1", - "express-rate-limit": "^7.1.5", - "helmet": "^7.1.0", - "ip-range-check": "^0.2.0", - "joi": "^17.11.0", - "jsonwebtoken": "^9.0.2", - "multer": "^2.1.1", - "pg": "^8.11.3", - "reflect-metadata": "^0.2.1", - "sanitize-html": "^2.13.0", - "sqlite3": "^5.1.7", - "stellar-sdk": "^11.2.0", - "typeorm": "^0.3.17", - "winston": "^3.11.0" - }, - "devDependencies": { - "@commitlint/cli": "^20.5.0", - "@commitlint/config-conventional": "^20.5.0", - "@types/bcrypt": "^5.0.2", - "@types/cors": "^2.8.17", - "@types/decimal.js": "^0.0.32", - "@types/express": "^5.0.0", - "@types/jest": "^29.5.14", - "@types/jsonwebtoken": "^9.0.5", - "@types/multer": "^2.1.0", - "@types/node": "^22.0.0", - "@types/sanitize-html": "^2.13.0", - "@types/supertest": "^6.0.3", - "@typescript-eslint/eslint-plugin": "^6.18.0", - "@typescript-eslint/parser": "^6.18.0", - "eslint": "^8.56.0", - "eslint-config-prettier": "^9.1.0", - "husky": "^9.1.7", - "jest": "^29.7.0", - "nodemon": "^3.0.2", - "prettier": "^3.2.4", - "supertest": "^6.3.4", - "ts-jest": "^29.4.12", - "ts-node": "^10.9.2", - "tsconfig-paths": "^4.2.0", - "typescript": "^5.3.3" - }, - "engines": { - "node": ">=22.0.0", - "npm": ">=10.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", - "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", - "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.29.0", - "@babel/types": "^7.29.0", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.29.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", - "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", - "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.29.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", - "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", - "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", - "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@colors/colors": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", - "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", - "license": "MIT", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@commitlint/cli": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-20.5.0.tgz", - "integrity": "sha512-yNkyN/tuKTJS3wdVfsZ2tXDM4G4Gi7z+jW54Cki8N8tZqwKBltbIvUUrSbT4hz1bhW/h0CdR+5sCSpXD+wMKaQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/format": "^20.5.0", - "@commitlint/lint": "^20.5.0", - "@commitlint/load": "^20.5.0", - "@commitlint/read": "^20.5.0", - "@commitlint/types": "^20.5.0", - "tinyexec": "^1.0.0", - "yargs": "^17.0.0" - }, - "bin": { - "commitlint": "cli.js" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/config-conventional": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-20.5.0.tgz", - "integrity": "sha512-t3Ni88rFw1XMa4nZHgOKJ8fIAT9M2j5TnKyTqJzsxea7FUetlNdYFus9dz+MhIRZmc16P0PPyEfh6X2d/qw8SA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/types": "^20.5.0", - "conventional-changelog-conventionalcommits": "^9.2.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/config-validator": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-20.5.0.tgz", - "integrity": "sha512-T/Uh6iJUzyx7j35GmHWdIiGRQB+ouZDk0pwAaYq4SXgB54KZhFdJ0vYmxiW6AMYICTIWuyMxDBl1jK74oFp/Gw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/types": "^20.5.0", - "ajv": "^8.11.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/ensure": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-20.5.0.tgz", - "integrity": "sha512-IpHqAUesBeW1EDDdjzJeaOxU9tnogLAyXLRBn03SHlj1SGENn2JGZqSWGkFvBJkJzfXAuCNtsoYzax+ZPS+puw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/types": "^20.5.0", - "lodash.camelcase": "^4.3.0", - "lodash.kebabcase": "^4.1.1", - "lodash.snakecase": "^4.1.1", - "lodash.startcase": "^4.4.0", - "lodash.upperfirst": "^4.3.1" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/execute-rule": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-20.0.0.tgz", - "integrity": "sha512-xyCoOShoPuPL44gVa+5EdZsBVao/pNzpQhkzq3RdtlFdKZtjWcLlUFQHSWBuhk5utKYykeJPSz2i8ABHQA+ZZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/format": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-20.5.0.tgz", - "integrity": "sha512-TI9EwFU/qZWSK7a5qyXMpKPPv3qta7FO4tKW+Wt2al7sgMbLWTsAcDpX1cU8k16TRdsiiet9aOw0zpvRXNJu7Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/types": "^20.5.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/is-ignored": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-20.5.0.tgz", - "integrity": "sha512-JWLarAsurHJhPozbuAH6GbP4p/hdOCoqS9zJMfqwswne+/GPs5V0+rrsfOkP68Y8PSLphwtFXV0EzJ+GTXTTGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/types": "^20.5.0", - "semver": "^7.6.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/lint": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-20.5.0.tgz", - "integrity": "sha512-jiM3hNUdu04jFBf1VgPdjtIPvbuVfDTBAc6L98AWcoLjF5sYqkulBHBzlVWll4rMF1T5zeQFB6r//a+s+BBKlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/is-ignored": "^20.5.0", - "@commitlint/parse": "^20.5.0", - "@commitlint/rules": "^20.5.0", - "@commitlint/types": "^20.5.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/load": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-20.5.0.tgz", - "integrity": "sha512-sLhhYTL/KxeOTZjjabKDhwidGZan84XKK1+XFkwDYL/4883kIajcz/dZFAhBJmZPtL8+nBx6bnkzA95YxPeDPw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/config-validator": "^20.5.0", - "@commitlint/execute-rule": "^20.0.0", - "@commitlint/resolve-extends": "^20.5.0", - "@commitlint/types": "^20.5.0", - "cosmiconfig": "^9.0.1", - "cosmiconfig-typescript-loader": "^6.1.0", - "is-plain-obj": "^4.1.0", - "lodash.mergewith": "^4.6.2", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/message": { - "version": "20.4.3", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-20.4.3.tgz", - "integrity": "sha512-6akwCYrzcrFcTYz9GyUaWlhisY4lmQ3KvrnabmhoeAV8nRH4dXJAh4+EUQ3uArtxxKQkvxJS78hNX2EU3USgxQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/parse": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-20.5.0.tgz", - "integrity": "sha512-SeKWHBMk7YOTnnEWUhx+d1a9vHsjjuo6Uo1xRfPNfeY4bdYFasCH1dDpAv13Lyn+dDPOels+jP6D2GRZqzc5fA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/types": "^20.5.0", - "conventional-changelog-angular": "^8.2.0", - "conventional-commits-parser": "^6.3.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/read": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-20.5.0.tgz", - "integrity": "sha512-JDEIJ2+GnWpK8QqwfmW7O42h0aycJEWNqcdkJnyzLD11nf9dW2dWLTVEa8Wtlo4IZFGLPATjR5neA5QlOvIH1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/top-level": "^20.4.3", - "@commitlint/types": "^20.5.0", - "git-raw-commits": "^5.0.0", - "minimist": "^1.2.8", - "tinyexec": "^1.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/resolve-extends": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-20.5.0.tgz", - "integrity": "sha512-3SHPWUW2v0tyspCTcfSsYml0gses92l6TlogwzvM2cbxDgmhSRc+fldDjvGkCXJrjSM87BBaWYTPWwwyASZRrg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/config-validator": "^20.5.0", - "@commitlint/types": "^20.5.0", - "global-directory": "^4.0.1", - "import-meta-resolve": "^4.0.0", - "lodash.mergewith": "^4.6.2", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/rules": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-20.5.0.tgz", - "integrity": "sha512-5NdQXQEdnDPT5pK8O39ZA7HohzPRHEsDGU23cyVCNPQy4WegAbAwrQk3nIu7p2sl3dutPk8RZd91yKTrMTnRkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/ensure": "^20.5.0", - "@commitlint/message": "^20.4.3", - "@commitlint/to-lines": "^20.0.0", - "@commitlint/types": "^20.5.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/to-lines": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-20.0.0.tgz", - "integrity": "sha512-2l9gmwiCRqZNWgV+pX1X7z4yP0b3ex/86UmUFgoRt672Ez6cAM2lOQeHFRUTuE6sPpi8XBCGnd8Kh3bMoyHwJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/top-level": { - "version": "20.4.3", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-20.4.3.tgz", - "integrity": "sha512-qD9xfP6dFg5jQ3NMrOhG0/w5y3bBUsVGyJvXxdWEwBm8hyx4WOk3kKXw28T5czBYvyeCVJgJJ6aoJZUWDpaacQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/types": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-20.5.0.tgz", - "integrity": "sha512-ZJoS8oSq2CAZEpc/YI9SulLrdiIyXeHb/OGqGrkUP6Q7YV+0ouNAa7GjqRdXeQPncHQIDz/jbCTlHScvYvO/gA==", - "dev": true, - "license": "MIT", - "dependencies": { - "conventional-commits-parser": "^6.3.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@conventional-changelog/git-client": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@conventional-changelog/git-client/-/git-client-2.6.0.tgz", - "integrity": "sha512-T+uPDciKf0/ioNNDpMGc8FDsehJClZP0yR3Q5MN6wE/Y/1QZ7F+80OgznnTCOlMEG4AV0LvH2UJi3C/nBnaBUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@simple-libs/child-process-utils": "^1.0.0", - "@simple-libs/stream-utils": "^1.2.0", - "semver": "^7.5.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "conventional-commits-filter": "^5.0.0", - "conventional-commits-parser": "^6.3.0" - }, - "peerDependenciesMeta": { - "conventional-commits-filter": { - "optional": true - }, - "conventional-commits-parser": { - "optional": true - } - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@dabh/diagnostics": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.8.tgz", - "integrity": "sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q==", - "license": "MIT", - "dependencies": { - "@so-ric/colorspace": "^1.1.6", - "enabled": "2.0.x", - "kuler": "^2.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", - "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", - "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", - "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "license": "MIT", - "optional": true - }, - "node_modules/@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", - "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", - "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", - "license": "BSD-3-Clause", - "dependencies": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" - } - }, - "node_modules/@noble/hashes": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@npmcli/fs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", - "license": "ISC", - "optional": true, - "dependencies": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" - } - }, - "node_modules/@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "license": "MIT", - "optional": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@paralleldrive/cuid2": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", - "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@noble/hashes": "^1.1.5" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@sideway/address": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", - "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", - "license": "BSD-3-Clause" - }, - "node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@simple-libs/child-process-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@simple-libs/child-process-utils/-/child-process-utils-1.0.2.tgz", - "integrity": "sha512-/4R8QKnd/8agJynkNdJmNw2MBxuFTRcNFnE5Sg/G+jkSsV8/UBgULMzhizWWW42p8L5H7flImV2ATi79Ove2Tw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@simple-libs/stream-utils": "^1.2.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://ko-fi.com/dangreen" - } - }, - "node_modules/@simple-libs/stream-utils": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@simple-libs/stream-utils/-/stream-utils-1.2.0.tgz", - "integrity": "sha512-KxXvfapcixpz6rVEB6HPjOUZT22yN6v0vI0urQSk1L8MlEWPDFCZkhw2xmkyoTGYeFw7tWTZd7e3lVzRZRN/EA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://ko-fi.com/dangreen" - } - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.10", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", - "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", - "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/@so-ric/colorspace": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@so-ric/colorspace/-/colorspace-1.1.6.tgz", - "integrity": "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==", - "license": "MIT", - "dependencies": { - "color": "^5.0.2", - "text-hex": "1.0.x" - } - }, - "node_modules/@sqltools/formatter": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", - "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==", - "license": "MIT" - }, - "node_modules/@stellar/js-xdr": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@stellar/js-xdr/-/js-xdr-3.1.2.tgz", - "integrity": "sha512-VVolPL5goVEIsvuGqDc5uiKxV03lzfWdvYg1KikvwheDmTBO68CKDji3bAZ/kppZrx5iTA8z3Ld5yuytcvhvOQ==", - "license": "Apache-2.0" - }, - "node_modules/@stellar/stellar-base": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/@stellar/stellar-base/-/stellar-base-11.0.1.tgz", - "integrity": "sha512-VQh+1KEtFjegD6spx08+lENt8tQOkQQQZoLtqExjpRXyWlqDhEe+bXMlBTYKDc5MIynHyD42RPEib27UG17trA==", - "license": "Apache-2.0", - "dependencies": { - "@stellar/js-xdr": "^3.1.1", - "base32.js": "^0.1.0", - "bignumber.js": "^9.1.2", - "buffer": "^6.0.3", - "sha.js": "^2.3.6", - "tweetnacl": "^1.0.3" - }, - "optionalDependencies": { - "sodium-native": "^4.0.10" - } - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", - "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", - "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.2" - } - }, - "node_modules/@types/bcrypt": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz", - "integrity": "sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.6", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", - "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/cookiejar": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", - "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/cors": { - "version": "2.8.19", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", - "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/decimal.js": { - "version": "0.0.32", - "resolved": "https://registry.npmjs.org/@types/decimal.js/-/decimal.js-0.0.32.tgz", - "integrity": "sha512-qiZoeFWRa6SaedYkSV8VrGV8xDGV3C6usFlUKOOl/fpvVdKVx+eHm+yHjJbGIuHgNsoe24wUddwLJGVBZFM5Ow==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/express": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz", - "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^5.0.0", - "@types/serve-static": "^2" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz", - "integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/http-errors": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", - "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/jest": { - "version": "29.5.14", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", - "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/jsonwebtoken": { - "version": "9.0.10", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", - "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/ms": "*", - "@types/node": "*" - } - }, - "node_modules/@types/methods": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", - "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/multer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.1.0.tgz", - "integrity": "sha512-zYZb0+nJhOHtPpGDb3vqPjwpdeGlGC157VpkqNQL+UU2qwoacoQ7MpsAmUptI/0Oa127X32JzWDqQVEXp2RcIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/node": { - "version": "22.19.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.15.tgz", - "integrity": "sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/qs": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.0.tgz", - "integrity": "sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/sanitize-html": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.16.1.tgz", - "integrity": "sha512-n9wjs8bCOTyN/ynwD8s/nTcTreIHB1vf31vhLMGqUPNHaweKC4/fAl4Dj+hUlCTKYgm4P3k83fmiFfzkZ6sgMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "htmlparser2": "^10.1" - } - }, - "node_modules/@types/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/send": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", - "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-2.2.0.tgz", - "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*" - } - }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/superagent": { - "version": "8.1.9", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.9.tgz", - "integrity": "sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/cookiejar": "^2.1.5", - "@types/methods": "^1.1.4", - "@types/node": "*", - "form-data": "^4.0.0" - } - }, - "node_modules/@types/supertest": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.3.tgz", - "integrity": "sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/methods": "^1.1.4", - "@types/superagent": "^8.1.0" - } - }, - "node_modules/@types/triple-beam": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", - "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", - "license": "MIT" - }, - "node_modules/@types/yargs": { - "version": "17.0.35", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", - "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", - "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/type-utils": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.4", - "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", - "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", - "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "semver": "^7.5.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", - "dev": true, - "license": "ISC" - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "license": "ISC" - }, - "node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "license": "MIT", - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", - "devOptional": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.5", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", - "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agentkeepalive": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", - "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "license": "MIT", - "optional": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ansis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", - "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", - "license": "ISC", - "engines": { - "node": ">=14" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/app-root-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", - "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", - "license": "MIT", - "engines": { - "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.1.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", - "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", - "license": "ISC" - }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", - "dev": true, - "license": "MIT" - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true, - "license": "MIT" - }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "license": "MIT" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "license": "MIT" - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "license": "MIT", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axios": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.14.0.tgz", - "integrity": "sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.11", - "form-data": "^4.0.5", - "proxy-from-env": "^2.1.0" - } - }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", - "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5" - }, - "peerDependencies": { - "@babel/core": "^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "dev": true, - "license": "MIT", - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" - }, - "node_modules/bare-addon-resolve": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/bare-addon-resolve/-/bare-addon-resolve-1.10.0.tgz", - "integrity": "sha512-sSd0jieRJlDaODOzj0oe0RjFVC1QI0ZIjGIdPkbrTXsdVVtENg14c+lHHAhHwmWCZ2nQlMhy8jA3Y5LYPc/isA==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "bare-module-resolve": "^1.10.0", - "bare-semver": "^1.0.0" - }, - "peerDependencies": { - "bare-url": "*" - }, - "peerDependenciesMeta": { - "bare-url": { - "optional": true - } - } - }, - "node_modules/bare-module-resolve": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/bare-module-resolve/-/bare-module-resolve-1.12.1.tgz", - "integrity": "sha512-hbmAPyFpEq8FoZMd5sFO3u6MC5feluWoGE8YKlA8fCrl6mNtx68Wjg4DTiDJcqRJaovTvOYKfYngoBUnbaT7eg==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "bare-semver": "^1.0.0" - }, - "peerDependencies": { - "bare-url": "*" - }, - "peerDependenciesMeta": { - "bare-url": { - "optional": true - } - } - }, - "node_modules/bare-semver": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bare-semver/-/bare-semver-1.0.2.tgz", - "integrity": "sha512-ESVaN2nzWhcI5tf3Zzcq9aqCZ676VWzqw07eEZ0qxAcEOAFYBa0pWq8sK34OQeHLY3JsfKXZS9mDyzyxGjeLzA==", - "license": "Apache-2.0", - "optional": true - }, - "node_modules/base32.js": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.1.0.tgz", - "integrity": "sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==", - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/baseline-browser-mapping": { - "version": "2.10.12", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.12.tgz", - "integrity": "sha512-qyq26DxfY4awP2gIRXhhLWfwzwI+N5Nxk6iQi8EFizIaWIjqicQTE4sLnZZVdeKPRcVNoJOkkpfzoIYuvCKaIQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.cjs" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/bcrypt": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", - "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.11", - "node-addon-api": "^5.0.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/bignumber.js": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", - "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "license": "MIT", - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bl/node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/body-parser": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", - "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", - "license": "MIT", - "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.3", - "http-errors": "^2.0.0", - "iconv-lite": "^0.7.0", - "on-finished": "^2.4.1", - "qs": "^6.14.1", - "raw-body": "^3.0.1", - "type-is": "^2.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/brace-expansion": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", - "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-json-stable-stringify": "2.x" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", - "license": "BSD-3-Clause" - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "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", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cacache": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "license": "ISC", - "optional": true, - "dependencies": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/cacache/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "license": "ISC", - "optional": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cacache/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC", - "optional": true - }, - "node_modules/call-bind": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001781", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001781.tgz", - "integrity": "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cjs-module-lexer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", - "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", - "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", - "dev": true, - "license": "MIT" - }, - "node_modules/color": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/color/-/color-5.0.3.tgz", - "integrity": "sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==", - "license": "MIT", - "dependencies": { - "color-convert": "^3.1.3", - "color-string": "^2.1.3" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/color-string": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-2.1.4.tgz", - "integrity": "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==", - "license": "MIT", - "dependencies": { - "color-name": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/color-string/node_modules/color-name": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", - "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", - "license": "MIT", - "engines": { - "node": ">=12.20" - } - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "license": "ISC", - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/color/node_modules/color-convert": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.3.tgz", - "integrity": "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==", - "license": "MIT", - "dependencies": { - "color-name": "^2.0.0" - }, - "engines": { - "node": ">=14.6" - } - }, - "node_modules/color/node_modules/color-name": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", - "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", - "license": "MIT", - "engines": { - "node": ">=12.20" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/compare-func": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" - } - }, - "node_modules/component-emitter": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", - "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "license": "MIT" - }, - "node_modules/concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "engines": [ - "node >= 6.0" - ], - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "license": "ISC" - }, - "node_modules/content-disposition": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", - "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/conventional-changelog-angular": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-8.3.1.tgz", - "integrity": "sha512-6gfI3otXK5Ph5DfCOI1dblr+kN3FAm5a97hYoQkqNZxOaYa5WKfXH+AnpsmS+iUH2mgVC2Cg2Qw9m5OKcmNrIg==", - "dev": true, - "license": "ISC", - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-changelog-conventionalcommits": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-9.3.1.tgz", - "integrity": "sha512-dTYtpIacRpcZgrvBYvBfArMmK2xvIpv2TaxM0/ZI5CBtNUzvF2x0t15HsbRABWprS6UPmvj+PzHVjSx4qAVKyw==", - "dev": true, - "license": "ISC", - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-commits-parser": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-6.4.0.tgz", - "integrity": "sha512-tvRg7FIBNlyPzjdG8wWRlPHQJJHI7DylhtRGeU9Lq+JuoPh5BKpPRX83ZdLrvXuOSu5Eo/e7SzOQhU4Hd2Miuw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@simple-libs/stream-utils": "^1.2.0", - "meow": "^13.0.0" - }, - "bin": { - "conventional-commits-parser": "dist/cli/index.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", - "license": "MIT", - "engines": { - "node": ">=6.6.0" - } - }, - "node_modules/cookiejar": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", - "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", - "dev": true, - "license": "MIT" - }, - "node_modules/cors": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", - "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/cosmiconfig": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.1.tgz", - "integrity": "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/cosmiconfig-typescript-loader": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-6.2.0.tgz", - "integrity": "sha512-GEN39v7TgdxgIoNcdkRE3uiAzQt3UXLyHbRHD6YoL048XAeOomyxaP+Hh/+2C6C2wYjxJ2onhJcsQp+L4YEkVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "jiti": "^2.6.1" - }, - "engines": { - "node": ">=v18" - }, - "peerDependencies": { - "@types/node": "*", - "cosmiconfig": ">=9", - "typescript": ">=5" - } - }, - "node_modules/create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "bin": { - "create-jest": "bin/create-jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/dayjs": { - "version": "1.11.20", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.20.tgz", - "integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==", - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decimal.js": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", - "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", - "license": "MIT" - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "license": "MIT", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/dedent": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz", - "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==", - "license": "MIT", - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "license": "MIT" - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/dezalgo": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", - "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", - "dev": true, - "license": "ISC", - "dependencies": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "node_modules/diff": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", - "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", - "devOptional": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/dom-serializer/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", - "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "license": "MIT" - }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.328", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.328.tgz", - "integrity": "sha512-QNQ5l45DzYytThO21403XN3FvK0hOkWDG8viNf6jqS42msJ8I4tGDSpBCgvDRRPnkffafiwAym2X2eHeGD2V0w==", - "dev": true, - "license": "ISC" - }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/enabled": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", - "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/entities": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", - "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "license": "MIT", - "optional": true - }, - "node_modules/error-ex": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-prettier": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.2.tgz", - "integrity": "sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ==", - "dev": true, - "license": "MIT", - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", - "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", - "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventsource": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz", - "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==", - "license": "MIT", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "license": "(MIT OR WTFPL)", - "engines": { - "node": ">=6" - } - }, - "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/express": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", - "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", - "license": "MIT", - "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.1", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "depd": "^2.0.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express-rate-limit": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz", - "integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://github.com/sponsors/express-rate-limit" - }, - "peerDependencies": { - "express": ">= 4.11" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/fastq": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", - "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/fecha": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", - "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", - "license": "MIT" - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "license": "MIT" - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", - "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", - "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", - "dev": true, - "license": "ISC" - }, - "node_modules/fn.name": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", - "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", - "license": "MIT" - }, - "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-each": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/form-data/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/form-data/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/formidable": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.5.tgz", - "integrity": "sha512-Oz5Hwvwak/DCaXVVUtPn4oLMLLy1CdclLKO1LFgU7XzDpVMUU5UjlSLpGMocyQNNk8F6IJW9M/YdooSn2MRI+Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@paralleldrive/cuid2": "^2.2.2", - "dezalgo": "^1.0.4", - "once": "^1.4.0", - "qs": "^6.11.0" - }, - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "license": "MIT" - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/git-raw-commits": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-5.0.1.tgz", - "integrity": "sha512-Y+csSm2GD/PCSh6Isd/WiMjNAydu0VBiG9J7EdQsNA5P9uXvLayqjmTsNlK5Gs9IhblFZqOU0yid5Il5JPoLiQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@conventional-changelog/git-client": "^2.6.0", - "meow": "^13.0.0" - }, - "bin": { - "git-raw-commits": "src/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "license": "MIT" - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", - "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/global-directory": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", - "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ini": "4.1.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "devOptional": true, - "license": "ISC" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, - "node_modules/handlebars": { - "version": "4.7.9", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", - "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "license": "ISC" - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/helmet": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.2.0.tgz", - "integrity": "sha512-ZRiwvN089JfMXokizgqEPXsl2Guk094yExfoDXR0cBYWxtBbaSww/w+vT4WEJsBW2iTUi1GgZ6swmoug3Oy4Xw==", - "license": "MIT", - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true, - "license": "MIT" - }, - "node_modules/htmlparser2": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", - "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.2.2", - "entities": "^7.0.1" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", - "license": "BSD-2-Clause", - "optional": true - }, - "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "license": "MIT", - "optional": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "ms": "^2.0.0" - } - }, - "node_modules/husky": { - "version": "9.1.7", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", - "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", - "dev": true, - "license": "MIT", - "bin": { - "husky": "bin.js" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/iconv-lite": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", - "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", - "dev": true, - "license": "ISC" - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-meta-resolve": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", - "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "license": "ISC", - "optional": true - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ini": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", - "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/ip-address": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", - "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/ip-range-check": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ip-range-check/-/ip-range-check-0.2.1.tgz", - "integrity": "sha512-qm1B6kp3gKxUoRiNW1ZJZcWGAGWQSfg3CxCTugWNXb+p6iymUQ2RBHUvObzh0QNiDyjoq6XsGiemBru1RMlNkw==", - "license": "MIT", - "dependencies": { - "ipaddr.js": "^2.5.0" - } - }, - "node_modules/ip-range-check/node_modules/ipaddr.js": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.5.0.tgz", - "integrity": "sha512-aq+t5NAc+cS6rZQQVWC2x98CPqGtKKTMDd4Gaodv0wShnItdKg/51djkGJ1hqH+Oy0ivDftCbSLCQob8zso01w==", - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "license": "MIT", - "optional": true - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-plain-object": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.1.0.tgz", - "integrity": "sha512-bUi/yjmtKYcRVUtWRGr0UA6xEFh2I6zWUwMrUXB3s7bmYCaZ8a+0ZsTRkrawh/mzlSD1Y0Ph8bp/U+TvBpWDNw==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "license": "MIT" - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", - "license": "MIT", - "dependencies": { - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC" - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", - "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-circus": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/jiti": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", - "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, - "node_modules/joi": { - "version": "17.13.3", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", - "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^9.3.0", - "@hapi/topo": "^5.1.0", - "@sideway/address": "^4.1.5", - "@sideway/formula": "^3.0.1", - "@sideway/pinpoint": "^2.0.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonwebtoken": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", - "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", - "license": "MIT", - "dependencies": { - "jws": "^4.0.1", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=12", - "npm": ">=6" - } - }, - "node_modules/jwa": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", - "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", - "license": "MIT", - "dependencies": { - "buffer-equal-constant-time": "^1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", - "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", - "license": "MIT", - "dependencies": { - "jwa": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/kuler": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", - "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", - "license": "MIT" - }, - "node_modules/launder": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/launder/-/launder-1.7.1.tgz", - "integrity": "sha512-mU6WRz5EusL9ZZuiZ5SO4Y6C0P9PAUR9iwdb6bzj4KDihm28DiHFw+/yk9DBH4f+Pv1wuzQ4e2jV3oQ7mkIqvw==", - "license": "MIT", - "dependencies": { - "dayjs": "^1.11.7" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "license": "MIT" - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", - "license": "MIT" - }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", - "license": "MIT" - }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", - "license": "MIT" - }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", - "license": "MIT" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "license": "MIT" - }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", - "license": "MIT" - }, - "node_modules/lodash.kebabcase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.mergewith": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", - "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", - "license": "MIT" - }, - "node_modules/lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.startcase": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", - "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.upperfirst": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", - "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", - "dev": true, - "license": "MIT" - }, - "node_modules/logform": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", - "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", - "license": "MIT", - "dependencies": { - "@colors/colors": "1.6.0", - "@types/triple-beam": "^1.3.2", - "fecha": "^4.2.0", - "ms": "^2.1.1", - "safe-stable-stringify": "^2.3.1", - "triple-beam": "^1.3.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "devOptional": true, - "license": "ISC" - }, - "node_modules/make-fetch-happen": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", - "license": "ISC", - "optional": true, - "dependencies": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.2.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.2", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^6.0.0", - "ssri": "^8.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "license": "ISC", - "optional": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-fetch-happen/node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/make-fetch-happen/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC", - "optional": true - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "tmpl": "1.0.5" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/meow": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", - "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "license": "ISC", - "optional": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-fetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", - "license": "MIT", - "optional": true, - "dependencies": { - "minipass": "^3.1.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "optionalDependencies": { - "encoding": "^0.1.12" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.7.tgz", - "integrity": "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==", - "license": "BlueOak-1.0.0", - "optional": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "license": "ISC", - "optional": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "license": "ISC", - "optional": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "license": "MIT" - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/multer": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/multer/-/multer-2.1.1.tgz", - "integrity": "sha512-mo+QTzKlx8R7E5ylSXxWzGoXoZbOsRMpyitcht8By2KHvMbf3tjwosZ/Mu/XYU6UuJ3VZnODIrak5ZrPiPyB6A==", - "license": "MIT", - "dependencies": { - "append-field": "^1.0.0", - "busboy": "^1.6.0", - "concat-stream": "^2.0.0", - "type-is": "^1.6.18" - }, - "engines": { - "node": ">= 10.16.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/multer/node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/multer/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/multer/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/multer/node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/nanoid": { - "version": "3.3.18", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", - "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/napi-build-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", - "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", - "license": "MIT" - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-abi": { - "version": "3.89.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.89.0.tgz", - "integrity": "sha512-6u9UwL0HlAl21+agMN3YAMXcKByMqwGx+pq+P76vii5f7hTPtKDp08/H9py6DY+cfDw7kQNTGEj/rly3IgbNQA==", - "license": "MIT", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", - "license": "MIT" - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-gyp": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", - "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", - "license": "MIT", - "optional": true, - "dependencies": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^9.1.0", - "nopt": "^5.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": ">= 10.12.0" - } - }, - "node_modules/node-gyp/node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "optional": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/node-gyp/node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "optional": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/node-gyp/node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "optional": true, - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-releases": { - "version": "2.0.36", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", - "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nodemon": { - "version": "3.1.14", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz", - "integrity": "sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": "^3.5.2", - "debug": "^4", - "ignore-by-default": "^1.0.1", - "minimatch": "^10.2.1", - "pstree.remy": "^1.1.8", - "semver": "^7.5.3", - "simple-update-notifier": "^2.0.0", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.5" - }, - "bin": { - "nodemon": "bin/nodemon.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nodemon" - } - }, - "node_modules/nodemon/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/nodemon/node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/nodemon/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/nodemon/node_modules/minimatch": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", - "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/nodemon/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "license": "ISC", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/one-time": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", - "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", - "license": "MIT", - "dependencies": { - "fn.name": "1.x.x" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "license": "BlueOak-1.0.0" - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-srcset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", - "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==", - "license": "MIT" - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" - }, - "node_modules/path-scurry/node_modules/minipass": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", - "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/path-to-regexp": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.0.tgz", - "integrity": "sha512-PuseHIvAnz3bjrM2rGJtSgo1zjgxapTLZ7x2pjhzWwlp4SJQgK3f3iZIQwkpEnBaKz6seKBADpM4B4ySkuYypg==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/pg": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.20.0.tgz", - "integrity": "sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA==", - "license": "MIT", - "dependencies": { - "pg-connection-string": "^2.12.0", - "pg-pool": "^3.13.0", - "pg-protocol": "^1.13.0", - "pg-types": "2.2.0", - "pgpass": "1.0.5" - }, - "engines": { - "node": ">= 16.0.0" - }, - "optionalDependencies": { - "pg-cloudflare": "^1.3.0" - }, - "peerDependencies": { - "pg-native": ">=3.0.1" - }, - "peerDependenciesMeta": { - "pg-native": { - "optional": true - } - } - }, - "node_modules/pg-cloudflare": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz", - "integrity": "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==", - "license": "MIT", - "optional": true - }, - "node_modules/pg-connection-string": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.12.0.tgz", - "integrity": "sha512-U7qg+bpswf3Cs5xLzRqbXbQl85ng0mfSV/J0nnA31MCLgvEaAo7CIhmeyrmJpOr7o+zm0rXK+hNnT5l9RHkCkQ==", - "license": "MIT" - }, - "node_modules/pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "license": "ISC", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/pg-pool": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.13.0.tgz", - "integrity": "sha512-gB+R+Xud1gLFuRD/QgOIgGOBE2KCQPaPwkzBBGC9oG69pHTkhQeIuejVIk3/cnDyX39av2AxomQiyPT13WKHQA==", - "license": "MIT", - "peerDependencies": { - "pg": ">=8.0" - } - }, - "node_modules/pg-protocol": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.13.0.tgz", - "integrity": "sha512-zzdvXfS6v89r6v7OcFCHfHlyG/wvry1ALxZo4LqgUoy7W9xhBDMaqOuMiF3qEV45VqsN6rdlcehHrfDtlCPc8w==", - "license": "MIT" - }, - "node_modules/pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "license": "MIT", - "dependencies": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pgpass": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "license": "MIT", - "dependencies": { - "split2": "^4.1.0" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pirates": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", - "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", - "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.5.26", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", - "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.17", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/postgres-bytea": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz", - "integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-date": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "license": "MIT", - "dependencies": { - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/prebuild-install": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", - "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", - "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", - "license": "MIT", - "dependencies": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^2.0.0", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "bin": { - "prebuild-install": "bin.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", - "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "license": "ISC", - "optional": true - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "license": "MIT", - "optional": true, - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-from-env": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", - "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true, - "license": "MIT" - }, - "node_modules/pump": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", - "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/pure-rand": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", - "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" - }, - "node_modules/qs": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", - "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", - "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.7.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "license": "ISC" - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true, - "license": "MIT" - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/reflect-metadata": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", - "license": "Apache-2.0" - }, - "node_modules/require-addon": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/require-addon/-/require-addon-1.2.0.tgz", - "integrity": "sha512-VNPDZlYgIYQwWp9jMTzljx+k0ZtatKlcvOhktZ/anNPI3dQ9NXk7cq2U4iJ1wd9IrytRnYhyEocFWbkdPb+MYA==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "bare-addon-resolve": "^1.3.0" - }, - "engines": { - "bare": ">=1.10.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.11", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve.exports": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", - "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/router": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", - "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "depd": "^2.0.0", - "is-promise": "^4.0.0", - "parseurl": "^1.3.3", - "path-to-regexp": "^8.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safe-stable-stringify": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", - "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/sanitize-html": { - "version": "2.17.7", - "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.17.7.tgz", - "integrity": "sha512-PGtEkc9cbnedU3s9TmzDbpsZ8w086g/0Q8k8/oIO1NLNU3i5k9yn835CrjJSajp1KMmkisbO1qPXxNKO3welAg==", - "license": "MIT", - "dependencies": { - "deepmerge": "^4.2.2", - "escape-string-regexp": "^4.0.0", - "htmlparser2": "^12.0.0", - "is-plain-object": "^5.0.0", - "launder": "^1.7.1", - "parse-srcset": "^1.0.2", - "postcss": "^8.3.11" - }, - "engines": { - "node": ">=22.12.0" - } - }, - "node_modules/sanitize-html/node_modules/dom-serializer": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-3.1.1.tgz", - "integrity": "sha512-4MEa38/QexBob6gFNwu+EGdWvhJ1OKuNwdYY3Y3NyeWDQfnGeDYQUDfIRzWu5B5gsv03so2Uxd28YC6zrsx3Lw==", - "license": "MIT", - "dependencies": { - "domelementtype": "^3.0.0", - "domhandler": "^6.0.0", - "entities": "^8.0.0" - }, - "engines": { - "node": ">=20.19.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/sanitize-html/node_modules/domelementtype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-3.0.0.tgz", - "integrity": "sha512-umCQid3jKbDmVjx8jGaW7uUykm4DEUeyV21hPxNMo2nV955DhUThwqyOIDtreepP31hl84X7G5U9ZfsWvIB3Pg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause", - "engines": { - "node": ">=20.19.0" - } - }, - "node_modules/sanitize-html/node_modules/domhandler": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-6.0.1.tgz", - "integrity": "sha512-gYzvtM72ZtxQO0T048kd6HWSbbGCNOUwcnfQ01cqIJ4X2IYKFFHZ5mKvrQETcFXxsRObZulDaKmy//R7TPtsBg==", - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^3.0.0" - }, - "engines": { - "node": ">=20.19.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/sanitize-html/node_modules/domutils": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-4.0.2.tgz", - "integrity": "sha512-qI4JLRKnSzqFqr7hAlS5xQDusBCjKSEG4t4+7aNrIQMHBcsC2TGEhuyABJdYkgSewL57PNLYEiibY2iPKhKpaA==", - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^3.0.0", - "domelementtype": "^3.0.0", - "domhandler": "^6.0.0" - }, - "engines": { - "node": ">=20.19.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/sanitize-html/node_modules/entities": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz", - "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=20.19.0" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/sanitize-html/node_modules/htmlparser2": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-12.0.0.tgz", - "integrity": "sha512-Tz7u1i95/g2x2jz81+x0FBVhBhY5aRTvD3tXXdFaljuNdzDLJ8UGNRrTcj2cgQvAg3iW/h77Fz15nLW0L0CrZw==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "MIT", - "dependencies": { - "domelementtype": "^3.0.0", - "domhandler": "^6.0.0", - "domutils": "^4.0.2", - "entities": "^8.0.0" - }, - "engines": { - "node": ">=20.19.0" - } - }, - "node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", - "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.3", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.1", - "mime-types": "^3.0.2", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/serve-static": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", - "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", - "license": "MIT", - "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "license": "ISC" - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "node_modules/sha.js": { - "version": "2.4.12", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", - "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", - "license": "(MIT AND BSD-3-Clause)", - "dependencies": { - "inherits": "^2.0.4", - "safe-buffer": "^5.2.1", - "to-buffer": "^1.2.0" - }, - "bin": { - "sha.js": "bin.js" - }, - "engines": { - "node": ">= 0.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "license": "ISC" - }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "node_modules/simple-update-notifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", - "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", - "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", - "license": "MIT", - "optional": true, - "dependencies": { - "ip-address": "^10.0.1", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", - "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/sodium-native": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.3.3.tgz", - "integrity": "sha512-OnxSlN3uyY8D0EsLHpmm2HOFmKddQVvEMmsakCrXUzSd8kjjbzL413t4ZNF3n0UxSwNgwTyUvkmZHTfuCeiYSw==", - "license": "MIT", - "optional": true, - "dependencies": { - "require-addon": "^1.1.0" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "license": "ISC", - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/sql-highlight": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/sql-highlight/-/sql-highlight-6.1.0.tgz", - "integrity": "sha512-ed7OK4e9ywpE7pgRMkMQmZDPKSVdm0oX5IEtZiKnFucSF0zu6c80GZBe38UqHuVhTWJ9xsKgSMjCG2bml86KvA==", - "funding": [ - "https://github.com/scriptcoded/sql-highlight?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/scriptcoded" - } - ], - "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "node_modules/sqlite3": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz", - "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "bindings": "^1.5.0", - "node-addon-api": "^7.0.0", - "prebuild-install": "^7.1.1", - "tar": "^6.1.11" - }, - "optionalDependencies": { - "node-gyp": "8.x" - }, - "peerDependencies": { - "node-gyp": "8.x" - }, - "peerDependenciesMeta": { - "node-gyp": { - "optional": true - } - } - }, - "node_modules/sqlite3/node_modules/node-addon-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "license": "MIT" - }, - "node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "license": "ISC", - "optional": true, - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/stellar-sdk": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/stellar-sdk/-/stellar-sdk-11.3.0.tgz", - "integrity": "sha512-xOp2zpQm5TIbgJi7wJhAmJh+Uy0ew5GbGtj1kZv6HEWHgSvW95xYMxGaw6MWM9r2YPUSQySboE6JwDc9jdx53A==", - "deprecated": "⚠️ This package has moved to @stellar/stellar-sdk! 🚚", - "license": "Apache-2.0", - "dependencies": { - "@stellar/stellar-base": "^11.0.1", - "axios": "^1.6.8", - "bignumber.js": "^9.1.2", - "eventsource": "^2.0.2", - "randombytes": "^2.1.0", - "toml": "^3.0.0", - "urijs": "^1.19.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", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/superagent": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz", - "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==", - "deprecated": "Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net", - "dev": true, - "license": "MIT", - "dependencies": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.4", - "debug": "^4.3.4", - "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.0", - "formidable": "^2.1.2", - "methods": "^1.1.2", - "mime": "2.6.0", - "qs": "^6.11.0", - "semver": "^7.3.8" - }, - "engines": { - "node": ">=6.4.0 <13 || >=14" - } - }, - "node_modules/supertest": { - "version": "6.3.4", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.4.tgz", - "integrity": "sha512-erY3HFDG0dPnhw4U+udPfrzXa4xhSG+n4rxfRuZWCUvjFWwKl+OxWf/7zk50s84/fAAs7vf5QAb9uRa0cCykxw==", - "deprecated": "Please upgrade to supertest v7.1.3+, see release notes at https://github.com/forwardemail/supertest/releases/tag/v7.1.3 - maintenance is supported by Forward Email @ https://forwardemail.net", - "dev": true, - "license": "MIT", - "dependencies": { - "methods": "^1.1.2", - "superagent": "^8.1.2" - }, - "engines": { - "node": ">=6.4.0" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar-fs": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", - "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", - "license": "MIT", - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/tar-fs/node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "license": "ISC" - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "license": "MIT", - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "license": "ISC", - "engines": { - "node": ">=8" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", - "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/text-hex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", - "license": "MIT" - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyexec": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", - "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/to-buffer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", - "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", - "license": "MIT", - "dependencies": { - "isarray": "^2.0.5", - "safe-buffer": "^5.2.1", - "typed-array-buffer": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/toml": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", - "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==", - "license": "MIT" - }, - "node_modules/touch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", - "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", - "dev": true, - "license": "ISC", - "bin": { - "nodetouch": "bin/nodetouch.js" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, - "node_modules/triple-beam": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", - "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", - "license": "MIT", - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/ts-jest": { - "version": "29.4.12", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.12.tgz", - "integrity": "sha512-Ov6ClY53Fflh6BGAnY2DlTq1hYDrTycz2PVTXBWFW2CU+9zrEqAp9fWdGXl42EXO5RLSFAcAZ2JFKbP+zBTFfw==", - "dev": true, - "license": "MIT", - "dependencies": { - "bs-logger": "^0.2.6", - "fast-json-stable-stringify": "^2.1.0", - "handlebars": "^4.7.9", - "json5": "^2.2.3", - "lodash.memoize": "^4.1.2", - "make-error": "^1.3.6", - "semver": "^7.8.5", - "type-fest": "^4.41.0", - "yargs-parser": "^21.1.1" - }, - "bin": { - "ts-jest": "cli.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/transform": "^29.0.0 || ^30.0.0", - "@jest/types": "^29.0.0 || ^30.0.0", - "babel-jest": "^29.0.0 || ^30.0.0", - "jest": "^29.0.0 || ^30.0.0", - "jest-util": "^29.0.0 || ^30.0.0", - "typescript": ">=4.3 <7" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/transform": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "jest-util": { - "optional": true - } - } - }, - "node_modules/ts-jest/node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/tsconfig-paths": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=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/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "license": "Unlicense" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", - "license": "MIT", - "dependencies": { - "content-type": "^1.0.5", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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.28", - "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.28.tgz", - "integrity": "sha512-6GH7wXhtfq2D33ZuRXYwIsl/qM5685WZcODZb7noOOcRMteM9KF2x2ap3H0EBjnSV0VO4gNAfJT5Ukp0PkOlvg==", - "license": "MIT", - "dependencies": { - "@sqltools/formatter": "^1.2.5", - "ansis": "^4.2.0", - "app-root-path": "^3.1.0", - "buffer": "^6.0.3", - "dayjs": "^1.11.19", - "debug": "^4.4.3", - "dedent": "^1.7.0", - "dotenv": "^16.6.1", - "glob": "^10.5.0", - "reflect-metadata": "^0.2.2", - "sha.js": "^2.4.12", - "sql-highlight": "^6.1.0", - "tslib": "^2.8.1", - "uuid": "^11.1.0", - "yargs": "^17.7.2" - }, - "bin": { - "typeorm": "cli.js", - "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js", - "typeorm-ts-node-esm": "cli-ts-node-esm.js" - }, - "engines": { - "node": ">=16.13.0" - }, - "funding": { - "url": "https://opencollective.com/typeorm" - }, - "peerDependencies": { - "@google-cloud/spanner": "^5.18.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", - "@sap/hana-client": "^2.14.22", - "better-sqlite3": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0", - "ioredis": "^5.0.4", - "mongodb": "^5.8.0 || ^6.0.0", - "mssql": "^9.1.1 || ^10.0.0 || ^11.0.0 || ^12.0.0", - "mysql2": "^2.2.5 || ^3.0.1", - "oracledb": "^6.3.0", - "pg": "^8.5.1", - "pg-native": "^3.0.0", - "pg-query-stream": "^4.0.0", - "redis": "^3.1.1 || ^4.0.0 || ^5.0.14", - "sql.js": "^1.4.0", - "sqlite3": "^5.0.3", - "ts-node": "^10.7.0", - "typeorm-aurora-data-api-driver": "^2.0.0 || ^3.0.0" - }, - "peerDependenciesMeta": { - "@google-cloud/spanner": { - "optional": true - }, - "@sap/hana-client": { - "optional": true - }, - "better-sqlite3": { - "optional": true - }, - "ioredis": { - "optional": true - }, - "mongodb": { - "optional": true - }, - "mssql": { - "optional": true - }, - "mysql2": { - "optional": true - }, - "oracledb": { - "optional": true - }, - "pg": { - "optional": true - }, - "pg-native": { - "optional": true - }, - "pg-query-stream": { - "optional": true - }, - "redis": { - "optional": true - }, - "sql.js": { - "optional": true - }, - "sqlite3": { - "optional": true - }, - "ts-node": { - "optional": true - }, - "typeorm-aurora-data-api-driver": { - "optional": true - } - } - }, - "node_modules/typeorm/node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/typeorm/node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.2" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/typeorm/node_modules/minipass": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", - "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "devOptional": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", - "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "dev": true, - "license": "MIT" - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "license": "ISC", - "optional": true, - "dependencies": { - "unique-slug": "^2.0.0" - } - }, - "node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "license": "ISC", - "optional": true, - "dependencies": { - "imurmurhash": "^0.1.4" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/urijs": { - "version": "1.19.11", - "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz", - "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==", - "license": "MIT" - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "license": "MIT" - }, - "node_modules/uuid": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", - "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/esm/bin/uuid" - } - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", - "dev": true, - "license": "ISC", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "makeerror": "1.0.12" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.20", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", - "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "for-each": "^0.3.5", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "license": "ISC", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/winston": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.19.0.tgz", - "integrity": "sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==", - "license": "MIT", - "dependencies": { - "@colors/colors": "^1.6.0", - "@dabh/diagnostics": "^2.0.8", - "async": "^3.2.3", - "is-stream": "^2.0.0", - "logform": "^2.7.0", - "one-time": "^1.0.0", - "readable-stream": "^3.4.0", - "safe-stable-stringify": "^2.3.1", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.9.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/winston-transport": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz", - "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", - "license": "MIT", - "dependencies": { - "logform": "^2.7.0", - "readable-stream": "^3.6.2", - "triple-beam": "^1.3.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "license": "ISC" - }, - "node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} +{ + "name": "stellarsettle-api", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "stellarsettle-api", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "bcrypt": "^5.1.1", + "cors": "^2.8.5", + "decimal.js": "^10.6.0", + "dotenv": "^16.3.1", + "express": "^5.2.1", + "express-rate-limit": "^7.1.5", + "helmet": "^7.1.0", + "ip-range-check": "^0.2.0", + "joi": "^17.11.0", + "jsonwebtoken": "^9.0.2", + "multer": "^2.1.1", + "pg": "^8.11.3", + "reflect-metadata": "^0.2.1", + "sanitize-html": "^2.13.0", + "sqlite3": "^5.1.7", + "stellar-sdk": "^11.2.0", + "typeorm": "^0.3.17", + "winston": "^3.11.0" + }, + "devDependencies": { + "@commitlint/cli": "^20.5.0", + "@commitlint/config-conventional": "^20.5.0", + "@types/bcrypt": "^5.0.2", + "@types/cors": "^2.8.17", + "@types/decimal.js": "^0.0.32", + "@types/express": "^5.0.0", + "@types/jest": "^29.5.14", + "@types/jsonwebtoken": "^9.0.5", + "@types/multer": "^2.1.0", + "@types/node": "^22.0.0", + "@types/sanitize-html": "^2.13.0", + "@types/supertest": "^6.0.3", + "@typescript-eslint/eslint-plugin": "^6.18.0", + "@typescript-eslint/parser": "^6.18.0", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "husky": "^9.1.7", + "jest": "^29.7.0", + "nodemon": "^3.0.2", + "prettier": "^3.2.4", + "supertest": "^6.3.4", + "ts-jest": "^29.4.12", + "ts-node": "^10.9.2", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.9.3" + }, + "engines": { + "node": ">=22.0.0", + "npm": ">=10.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", + "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@commitlint/cli": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-20.5.0.tgz", + "integrity": "sha512-yNkyN/tuKTJS3wdVfsZ2tXDM4G4Gi7z+jW54Cki8N8tZqwKBltbIvUUrSbT4hz1bhW/h0CdR+5sCSpXD+wMKaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/format": "^20.5.0", + "@commitlint/lint": "^20.5.0", + "@commitlint/load": "^20.5.0", + "@commitlint/read": "^20.5.0", + "@commitlint/types": "^20.5.0", + "tinyexec": "^1.0.0", + "yargs": "^17.0.0" + }, + "bin": { + "commitlint": "cli.js" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-conventional": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-20.5.0.tgz", + "integrity": "sha512-t3Ni88rFw1XMa4nZHgOKJ8fIAT9M2j5TnKyTqJzsxea7FUetlNdYFus9dz+MhIRZmc16P0PPyEfh6X2d/qw8SA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "conventional-changelog-conventionalcommits": "^9.2.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-validator": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-20.5.0.tgz", + "integrity": "sha512-T/Uh6iJUzyx7j35GmHWdIiGRQB+ouZDk0pwAaYq4SXgB54KZhFdJ0vYmxiW6AMYICTIWuyMxDBl1jK74oFp/Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "ajv": "^8.11.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/ensure": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-20.5.0.tgz", + "integrity": "sha512-IpHqAUesBeW1EDDdjzJeaOxU9tnogLAyXLRBn03SHlj1SGENn2JGZqSWGkFvBJkJzfXAuCNtsoYzax+ZPS+puw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "lodash.camelcase": "^4.3.0", + "lodash.kebabcase": "^4.1.1", + "lodash.snakecase": "^4.1.1", + "lodash.startcase": "^4.4.0", + "lodash.upperfirst": "^4.3.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/execute-rule": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-20.0.0.tgz", + "integrity": "sha512-xyCoOShoPuPL44gVa+5EdZsBVao/pNzpQhkzq3RdtlFdKZtjWcLlUFQHSWBuhk5utKYykeJPSz2i8ABHQA+ZZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/format": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-20.5.0.tgz", + "integrity": "sha512-TI9EwFU/qZWSK7a5qyXMpKPPv3qta7FO4tKW+Wt2al7sgMbLWTsAcDpX1cU8k16TRdsiiet9aOw0zpvRXNJu7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/is-ignored": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-20.5.0.tgz", + "integrity": "sha512-JWLarAsurHJhPozbuAH6GbP4p/hdOCoqS9zJMfqwswne+/GPs5V0+rrsfOkP68Y8PSLphwtFXV0EzJ+GTXTTGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "semver": "^7.6.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/lint": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-20.5.0.tgz", + "integrity": "sha512-jiM3hNUdu04jFBf1VgPdjtIPvbuVfDTBAc6L98AWcoLjF5sYqkulBHBzlVWll4rMF1T5zeQFB6r//a+s+BBKlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/is-ignored": "^20.5.0", + "@commitlint/parse": "^20.5.0", + "@commitlint/rules": "^20.5.0", + "@commitlint/types": "^20.5.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/load": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-20.5.0.tgz", + "integrity": "sha512-sLhhYTL/KxeOTZjjabKDhwidGZan84XKK1+XFkwDYL/4883kIajcz/dZFAhBJmZPtL8+nBx6bnkzA95YxPeDPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/config-validator": "^20.5.0", + "@commitlint/execute-rule": "^20.0.0", + "@commitlint/resolve-extends": "^20.5.0", + "@commitlint/types": "^20.5.0", + "cosmiconfig": "^9.0.1", + "cosmiconfig-typescript-loader": "^6.1.0", + "is-plain-obj": "^4.1.0", + "lodash.mergewith": "^4.6.2", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/message": { + "version": "20.4.3", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-20.4.3.tgz", + "integrity": "sha512-6akwCYrzcrFcTYz9GyUaWlhisY4lmQ3KvrnabmhoeAV8nRH4dXJAh4+EUQ3uArtxxKQkvxJS78hNX2EU3USgxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/parse": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-20.5.0.tgz", + "integrity": "sha512-SeKWHBMk7YOTnnEWUhx+d1a9vHsjjuo6Uo1xRfPNfeY4bdYFasCH1dDpAv13Lyn+dDPOels+jP6D2GRZqzc5fA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "conventional-changelog-angular": "^8.2.0", + "conventional-commits-parser": "^6.3.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/read": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-20.5.0.tgz", + "integrity": "sha512-JDEIJ2+GnWpK8QqwfmW7O42h0aycJEWNqcdkJnyzLD11nf9dW2dWLTVEa8Wtlo4IZFGLPATjR5neA5QlOvIH1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/top-level": "^20.4.3", + "@commitlint/types": "^20.5.0", + "git-raw-commits": "^5.0.0", + "minimist": "^1.2.8", + "tinyexec": "^1.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/resolve-extends": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-20.5.0.tgz", + "integrity": "sha512-3SHPWUW2v0tyspCTcfSsYml0gses92l6TlogwzvM2cbxDgmhSRc+fldDjvGkCXJrjSM87BBaWYTPWwwyASZRrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/config-validator": "^20.5.0", + "@commitlint/types": "^20.5.0", + "global-directory": "^4.0.1", + "import-meta-resolve": "^4.0.0", + "lodash.mergewith": "^4.6.2", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/rules": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-20.5.0.tgz", + "integrity": "sha512-5NdQXQEdnDPT5pK8O39ZA7HohzPRHEsDGU23cyVCNPQy4WegAbAwrQk3nIu7p2sl3dutPk8RZd91yKTrMTnRkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/ensure": "^20.5.0", + "@commitlint/message": "^20.4.3", + "@commitlint/to-lines": "^20.0.0", + "@commitlint/types": "^20.5.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/to-lines": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-20.0.0.tgz", + "integrity": "sha512-2l9gmwiCRqZNWgV+pX1X7z4yP0b3ex/86UmUFgoRt672Ez6cAM2lOQeHFRUTuE6sPpi8XBCGnd8Kh3bMoyHwJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/top-level": { + "version": "20.4.3", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-20.4.3.tgz", + "integrity": "sha512-qD9xfP6dFg5jQ3NMrOhG0/w5y3bBUsVGyJvXxdWEwBm8hyx4WOk3kKXw28T5czBYvyeCVJgJJ6aoJZUWDpaacQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/types": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-20.5.0.tgz", + "integrity": "sha512-ZJoS8oSq2CAZEpc/YI9SulLrdiIyXeHb/OGqGrkUP6Q7YV+0ouNAa7GjqRdXeQPncHQIDz/jbCTlHScvYvO/gA==", + "dev": true, + "license": "MIT", + "dependencies": { + "conventional-commits-parser": "^6.3.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@conventional-changelog/git-client": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@conventional-changelog/git-client/-/git-client-2.6.0.tgz", + "integrity": "sha512-T+uPDciKf0/ioNNDpMGc8FDsehJClZP0yR3Q5MN6wE/Y/1QZ7F+80OgznnTCOlMEG4AV0LvH2UJi3C/nBnaBUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@simple-libs/child-process-utils": "^1.0.0", + "@simple-libs/stream-utils": "^1.2.0", + "semver": "^7.5.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "conventional-commits-filter": "^5.0.0", + "conventional-commits-parser": "^6.3.0" + }, + "peerDependenciesMeta": { + "conventional-commits-filter": { + "optional": true + }, + "conventional-commits-parser": { + "optional": true + } + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.8.tgz", + "integrity": "sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q==", + "license": "MIT", + "dependencies": { + "@so-ric/colorspace": "^1.1.6", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "license": "MIT", + "optional": true + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "license": "BSD-3-Clause", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "license": "MIT", + "optional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@paralleldrive/cuid2": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", + "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.1.5" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "license": "BSD-3-Clause" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@simple-libs/child-process-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@simple-libs/child-process-utils/-/child-process-utils-1.0.2.tgz", + "integrity": "sha512-/4R8QKnd/8agJynkNdJmNw2MBxuFTRcNFnE5Sg/G+jkSsV8/UBgULMzhizWWW42p8L5H7flImV2ATi79Ove2Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@simple-libs/stream-utils": "^1.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://ko-fi.com/dangreen" + } + }, + "node_modules/@simple-libs/stream-utils": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@simple-libs/stream-utils/-/stream-utils-1.2.0.tgz", + "integrity": "sha512-KxXvfapcixpz6rVEB6HPjOUZT22yN6v0vI0urQSk1L8MlEWPDFCZkhw2xmkyoTGYeFw7tWTZd7e3lVzRZRN/EA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://ko-fi.com/dangreen" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.10", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", + "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", + "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/@so-ric/colorspace": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@so-ric/colorspace/-/colorspace-1.1.6.tgz", + "integrity": "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==", + "license": "MIT", + "dependencies": { + "color": "^5.0.2", + "text-hex": "1.0.x" + } + }, + "node_modules/@sqltools/formatter": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", + "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==", + "license": "MIT" + }, + "node_modules/@stellar/js-xdr": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@stellar/js-xdr/-/js-xdr-3.1.2.tgz", + "integrity": "sha512-VVolPL5goVEIsvuGqDc5uiKxV03lzfWdvYg1KikvwheDmTBO68CKDji3bAZ/kppZrx5iTA8z3Ld5yuytcvhvOQ==", + "license": "Apache-2.0" + }, + "node_modules/@stellar/stellar-base": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@stellar/stellar-base/-/stellar-base-11.0.1.tgz", + "integrity": "sha512-VQh+1KEtFjegD6spx08+lENt8tQOkQQQZoLtqExjpRXyWlqDhEe+bXMlBTYKDc5MIynHyD42RPEib27UG17trA==", + "license": "Apache-2.0", + "dependencies": { + "@stellar/js-xdr": "^3.1.1", + "base32.js": "^0.1.0", + "bignumber.js": "^9.1.2", + "buffer": "^6.0.3", + "sha.js": "^2.3.6", + "tweetnacl": "^1.0.3" + }, + "optionalDependencies": { + "sodium-native": "^4.0.10" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/bcrypt": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz", + "integrity": "sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookiejar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", + "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/cors": { + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/decimal.js": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/decimal.js/-/decimal.js-0.0.32.tgz", + "integrity": "sha512-qiZoeFWRa6SaedYkSV8VrGV8xDGV3C6usFlUKOOl/fpvVdKVx+eHm+yHjJbGIuHgNsoe24wUddwLJGVBZFM5Ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz", + "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "^2" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz", + "integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/methods": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", + "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/multer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.1.0.tgz", + "integrity": "sha512-zYZb0+nJhOHtPpGDb3vqPjwpdeGlGC157VpkqNQL+UU2qwoacoQ7MpsAmUptI/0Oa127X32JzWDqQVEXp2RcIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/node": { + "version": "22.19.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.15.tgz", + "integrity": "sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/qs": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/sanitize-html": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.16.1.tgz", + "integrity": "sha512-n9wjs8bCOTyN/ynwD8s/nTcTreIHB1vf31vhLMGqUPNHaweKC4/fAl4Dj+hUlCTKYgm4P3k83fmiFfzkZ6sgMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "htmlparser2": "^10.1" + } + }, + "node_modules/@types/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/superagent": { + "version": "8.1.9", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.9.tgz", + "integrity": "sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/cookiejar": "^2.1.5", + "@types/methods": "^1.1.4", + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/@types/supertest": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.3.tgz", + "integrity": "sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/methods": "^1.1.4", + "@types/superagent": "^8.1.0" + } + }, + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC" + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "devOptional": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", + "optional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", + "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/app-root-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", + "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", + "license": "MIT", + "engines": { + "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.1.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", + "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", + "license": "ISC" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "dev": true, + "license": "MIT" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axios": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.14.0.tgz", + "integrity": "sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/bare-addon-resolve": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/bare-addon-resolve/-/bare-addon-resolve-1.10.0.tgz", + "integrity": "sha512-sSd0jieRJlDaODOzj0oe0RjFVC1QI0ZIjGIdPkbrTXsdVVtENg14c+lHHAhHwmWCZ2nQlMhy8jA3Y5LYPc/isA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-module-resolve": "^1.10.0", + "bare-semver": "^1.0.0" + }, + "peerDependencies": { + "bare-url": "*" + }, + "peerDependenciesMeta": { + "bare-url": { + "optional": true + } + } + }, + "node_modules/bare-module-resolve": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/bare-module-resolve/-/bare-module-resolve-1.12.1.tgz", + "integrity": "sha512-hbmAPyFpEq8FoZMd5sFO3u6MC5feluWoGE8YKlA8fCrl6mNtx68Wjg4DTiDJcqRJaovTvOYKfYngoBUnbaT7eg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-semver": "^1.0.0" + }, + "peerDependencies": { + "bare-url": "*" + }, + "peerDependenciesMeta": { + "bare-url": { + "optional": true + } + } + }, + "node_modules/bare-semver": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bare-semver/-/bare-semver-1.0.2.tgz", + "integrity": "sha512-ESVaN2nzWhcI5tf3Zzcq9aqCZ676VWzqw07eEZ0qxAcEOAFYBa0pWq8sK34OQeHLY3JsfKXZS9mDyzyxGjeLzA==", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/base32.js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.1.0.tgz", + "integrity": "sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.12", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.12.tgz", + "integrity": "sha512-qyq26DxfY4awP2gIRXhhLWfwzwI+N5Nxk6iQi8EFizIaWIjqicQTE4sLnZZVdeKPRcVNoJOkkpfzoIYuvCKaIQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/body-parser": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "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", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001781", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001781.tgz", + "integrity": "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/color": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/color/-/color-5.0.3.tgz", + "integrity": "sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==", + "license": "MIT", + "dependencies": { + "color-convert": "^3.1.3", + "color-string": "^2.1.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/color-string": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-2.1.4.tgz", + "integrity": "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==", + "license": "MIT", + "dependencies": { + "color-name": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/color-string/node_modules/color-name": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/color/node_modules/color-convert": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.3.tgz", + "integrity": "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==", + "license": "MIT", + "dependencies": { + "color-name": "^2.0.0" + }, + "engines": { + "node": ">=14.6" + } + }, + "node_modules/color/node_modules/color-name": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC" + }, + "node_modules/content-disposition": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/conventional-changelog-angular": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-8.3.1.tgz", + "integrity": "sha512-6gfI3otXK5Ph5DfCOI1dblr+kN3FAm5a97hYoQkqNZxOaYa5WKfXH+AnpsmS+iUH2mgVC2Cg2Qw9m5OKcmNrIg==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-9.3.1.tgz", + "integrity": "sha512-dTYtpIacRpcZgrvBYvBfArMmK2xvIpv2TaxM0/ZI5CBtNUzvF2x0t15HsbRABWprS6UPmvj+PzHVjSx4qAVKyw==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/conventional-commits-parser": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-6.4.0.tgz", + "integrity": "sha512-tvRg7FIBNlyPzjdG8wWRlPHQJJHI7DylhtRGeU9Lq+JuoPh5BKpPRX83ZdLrvXuOSu5Eo/e7SzOQhU4Hd2Miuw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@simple-libs/stream-utils": "^1.2.0", + "meow": "^13.0.0" + }, + "bin": { + "conventional-commits-parser": "dist/cli/index.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cosmiconfig": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.1.tgz", + "integrity": "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig-typescript-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-6.2.0.tgz", + "integrity": "sha512-GEN39v7TgdxgIoNcdkRE3uiAzQt3UXLyHbRHD6YoL048XAeOomyxaP+Hh/+2C6C2wYjxJ2onhJcsQp+L4YEkVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "jiti": "^2.6.1" + }, + "engines": { + "node": ">=v18" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=9", + "typescript": ">=5" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/dayjs": { + "version": "1.11.20", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.20.tgz", + "integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "license": "MIT" + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dedent": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz", + "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==", + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "license": "ISC", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/diff": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.328", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.328.tgz", + "integrity": "sha512-QNQ5l45DzYytThO21403XN3FvK0hOkWDG8viNf6jqS42msJ8I4tGDSpBCgvDRRPnkffafiwAym2X2eHeGD2V0w==", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "license": "MIT", + "optional": true + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.2.tgz", + "integrity": "sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventsource": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz", + "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/express": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-rate-limit": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz", + "integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", + "license": "MIT" + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", + "license": "MIT" + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/form-data/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/formidable": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.5.tgz", + "integrity": "sha512-Oz5Hwvwak/DCaXVVUtPn4oLMLLy1CdclLKO1LFgU7XzDpVMUU5UjlSLpGMocyQNNk8F6IJW9M/YdooSn2MRI+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@paralleldrive/cuid2": "^2.2.2", + "dezalgo": "^1.0.4", + "once": "^1.4.0", + "qs": "^6.11.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-raw-commits": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-5.0.1.tgz", + "integrity": "sha512-Y+csSm2GD/PCSh6Isd/WiMjNAydu0VBiG9J7EdQsNA5P9uXvLayqjmTsNlK5Gs9IhblFZqOU0yid5Il5JPoLiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@conventional-changelog/git-client": "^2.6.0", + "meow": "^13.0.0" + }, + "bin": { + "git-raw-commits": "src/cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/global-directory": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", + "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "4.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/handlebars": { + "version": "4.7.9", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", + "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC" + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/helmet": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.2.0.tgz", + "integrity": "sha512-ZRiwvN089JfMXokizgqEPXsl2Guk094yExfoDXR0cBYWxtBbaSww/w+vT4WEJsBW2iTUi1GgZ6swmoug3Oy4Xw==", + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/htmlparser2": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", + "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "entities": "^7.0.1" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true, + "license": "ISC" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "license": "ISC", + "optional": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/ip-address": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-range-check": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ip-range-check/-/ip-range-check-0.2.1.tgz", + "integrity": "sha512-qm1B6kp3gKxUoRiNW1ZJZcWGAGWQSfg3CxCTugWNXb+p6iymUQ2RBHUvObzh0QNiDyjoq6XsGiemBru1RMlNkw==", + "license": "MIT", + "dependencies": { + "ipaddr.js": "^2.5.0" + } + }, + "node_modules/ip-range-check/node_modules/ipaddr.js": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.5.0.tgz", + "integrity": "sha512-aq+t5NAc+cS6rZQQVWC2x98CPqGtKKTMDd4Gaodv0wShnItdKg/51djkGJ1hqH+Oy0ivDftCbSLCQob8zso01w==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "license": "MIT", + "optional": true + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.1.0.tgz", + "integrity": "sha512-bUi/yjmtKYcRVUtWRGr0UA6xEFh2I6zWUwMrUXB3s7bmYCaZ8a+0ZsTRkrawh/mzlSD1Y0Ph8bp/U+TvBpWDNw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/joi": { + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "license": "MIT", + "dependencies": { + "jws": "^4.0.1", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", + "license": "MIT" + }, + "node_modules/launder": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/launder/-/launder-1.7.1.tgz", + "integrity": "sha512-mU6WRz5EusL9ZZuiZ5SO4Y6C0P9PAUR9iwdb6bzj4KDihm28DiHFw+/yk9DBH4f+Pv1wuzQ4e2jV3oQ7mkIqvw==", + "license": "MIT", + "dependencies": { + "dayjs": "^1.11.7" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.startcase": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.upperfirst": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", + "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/logform": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", + "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", + "license": "MIT", + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "license": "ISC", + "optional": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-fetch-happen/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/make-fetch-happen/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/meow": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", + "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.7.tgz", + "integrity": "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==", + "license": "BlueOak-1.0.0", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/multer": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.1.1.tgz", + "integrity": "sha512-mo+QTzKlx8R7E5ylSXxWzGoXoZbOsRMpyitcht8By2KHvMbf3tjwosZ/Mu/XYU6UuJ3VZnODIrak5ZrPiPyB6A==", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "type-is": "^1.6.18" + }, + "engines": { + "node": ">= 10.16.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/multer/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nanoid": { + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-abi": { + "version": "3.89.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.89.0.tgz", + "integrity": "sha512-6u9UwL0HlAl21+agMN3YAMXcKByMqwGx+pq+P76vii5f7hTPtKDp08/H9py6DY+cfDw7kQNTGEj/rly3IgbNQA==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "license": "MIT" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "license": "MIT", + "optional": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/node-gyp/node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nodemon": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz", + "integrity": "sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^10.2.1", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/nodemon/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "license": "MIT", + "dependencies": { + "fn.name": "1.x.x" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==", + "license": "MIT" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/path-scurry/node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/path-to-regexp": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.0.tgz", + "integrity": "sha512-PuseHIvAnz3bjrM2rGJtSgo1zjgxapTLZ7x2pjhzWwlp4SJQgK3f3iZIQwkpEnBaKz6seKBADpM4B4ySkuYypg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pg": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.20.0.tgz", + "integrity": "sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA==", + "license": "MIT", + "dependencies": { + "pg-connection-string": "^2.12.0", + "pg-pool": "^3.13.0", + "pg-protocol": "^1.13.0", + "pg-types": "2.2.0", + "pgpass": "1.0.5" + }, + "engines": { + "node": ">= 16.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.3.0" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz", + "integrity": "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==", + "license": "MIT", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.12.0.tgz", + "integrity": "sha512-U7qg+bpswf3Cs5xLzRqbXbQl85ng0mfSV/J0nnA31MCLgvEaAo7CIhmeyrmJpOr7o+zm0rXK+hNnT5l9RHkCkQ==", + "license": "MIT" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "license": "ISC", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.13.0.tgz", + "integrity": "sha512-gB+R+Xud1gLFuRD/QgOIgGOBE2KCQPaPwkzBBGC9oG69pHTkhQeIuejVIk3/cnDyX39av2AxomQiyPT13WKHQA==", + "license": "MIT", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.13.0.tgz", + "integrity": "sha512-zzdvXfS6v89r6v7OcFCHfHlyG/wvry1ALxZo4LqgUoy7W9xhBDMaqOuMiF3qEV45VqsN6rdlcehHrfDtlCPc8w==", + "license": "MIT" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "license": "MIT", + "dependencies": { + "split2": "^4.1.0" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.17", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz", + "integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "license": "ISC", + "optional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "license": "MIT", + "optional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true, + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "license": "Apache-2.0" + }, + "node_modules/require-addon": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/require-addon/-/require-addon-1.2.0.tgz", + "integrity": "sha512-VNPDZlYgIYQwWp9jMTzljx+k0ZtatKlcvOhktZ/anNPI3dQ9NXk7cq2U4iJ1wd9IrytRnYhyEocFWbkdPb+MYA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-addon-resolve": "^1.3.0" + }, + "engines": { + "bare": ">=1.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/sanitize-html": { + "version": "2.17.7", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.17.7.tgz", + "integrity": "sha512-PGtEkc9cbnedU3s9TmzDbpsZ8w086g/0Q8k8/oIO1NLNU3i5k9yn835CrjJSajp1KMmkisbO1qPXxNKO3welAg==", + "license": "MIT", + "dependencies": { + "deepmerge": "^4.2.2", + "escape-string-regexp": "^4.0.0", + "htmlparser2": "^12.0.0", + "is-plain-object": "^5.0.0", + "launder": "^1.7.1", + "parse-srcset": "^1.0.2", + "postcss": "^8.3.11" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/sanitize-html/node_modules/dom-serializer": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-3.1.1.tgz", + "integrity": "sha512-4MEa38/QexBob6gFNwu+EGdWvhJ1OKuNwdYY3Y3NyeWDQfnGeDYQUDfIRzWu5B5gsv03so2Uxd28YC6zrsx3Lw==", + "license": "MIT", + "dependencies": { + "domelementtype": "^3.0.0", + "domhandler": "^6.0.0", + "entities": "^8.0.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/sanitize-html/node_modules/domelementtype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-3.0.0.tgz", + "integrity": "sha512-umCQid3jKbDmVjx8jGaW7uUykm4DEUeyV21hPxNMo2nV955DhUThwqyOIDtreepP31hl84X7G5U9ZfsWvIB3Pg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/sanitize-html/node_modules/domhandler": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-6.0.1.tgz", + "integrity": "sha512-gYzvtM72ZtxQO0T048kd6HWSbbGCNOUwcnfQ01cqIJ4X2IYKFFHZ5mKvrQETcFXxsRObZulDaKmy//R7TPtsBg==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^3.0.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/sanitize-html/node_modules/domutils": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-4.0.2.tgz", + "integrity": "sha512-qI4JLRKnSzqFqr7hAlS5xQDusBCjKSEG4t4+7aNrIQMHBcsC2TGEhuyABJdYkgSewL57PNLYEiibY2iPKhKpaA==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^3.0.0", + "domelementtype": "^3.0.0", + "domhandler": "^6.0.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/sanitize-html/node_modules/entities": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz", + "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/sanitize-html/node_modules/htmlparser2": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-12.0.0.tgz", + "integrity": "sha512-Tz7u1i95/g2x2jz81+x0FBVhBhY5aRTvD3tXXdFaljuNdzDLJ8UGNRrTcj2cgQvAg3iW/h77Fz15nLW0L0CrZw==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^3.0.0", + "domhandler": "^6.0.0", + "domutils": "^4.0.2", + "entities": "^8.0.0" + }, + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/serve-static": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/sha.js": { + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" + }, + "bin": { + "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ip-address": "^10.0.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sodium-native": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.3.3.tgz", + "integrity": "sha512-OnxSlN3uyY8D0EsLHpmm2HOFmKddQVvEMmsakCrXUzSd8kjjbzL413t4ZNF3n0UxSwNgwTyUvkmZHTfuCeiYSw==", + "license": "MIT", + "optional": true, + "dependencies": { + "require-addon": "^1.1.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/sql-highlight": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/sql-highlight/-/sql-highlight-6.1.0.tgz", + "integrity": "sha512-ed7OK4e9ywpE7pgRMkMQmZDPKSVdm0oX5IEtZiKnFucSF0zu6c80GZBe38UqHuVhTWJ9xsKgSMjCG2bml86KvA==", + "funding": [ + "https://github.com/scriptcoded/sql-highlight?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/scriptcoded" + } + ], + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/sqlite3": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz", + "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.1", + "tar": "^6.1.11" + }, + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, + "node_modules/sqlite3/node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stellar-sdk": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/stellar-sdk/-/stellar-sdk-11.3.0.tgz", + "integrity": "sha512-xOp2zpQm5TIbgJi7wJhAmJh+Uy0ew5GbGtj1kZv6HEWHgSvW95xYMxGaw6MWM9r2YPUSQySboE6JwDc9jdx53A==", + "deprecated": "⚠️ This package has moved to @stellar/stellar-sdk! 🚚", + "license": "Apache-2.0", + "dependencies": { + "@stellar/stellar-base": "^11.0.1", + "axios": "^1.6.8", + "bignumber.js": "^9.1.2", + "eventsource": "^2.0.2", + "randombytes": "^2.1.0", + "toml": "^3.0.0", + "urijs": "^1.19.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", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/superagent": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz", + "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==", + "deprecated": "Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net", + "dev": true, + "license": "MIT", + "dependencies": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^2.1.2", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=6.4.0 <13 || >=14" + } + }, + "node_modules/supertest": { + "version": "6.3.4", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.4.tgz", + "integrity": "sha512-erY3HFDG0dPnhw4U+udPfrzXa4xhSG+n4rxfRuZWCUvjFWwKl+OxWf/7zk50s84/fAAs7vf5QAb9uRa0cCykxw==", + "deprecated": "Please upgrade to supertest v7.1.3+, see release notes at https://github.com/forwardemail/supertest/releases/tag/v7.1.3 - maintenance is supported by Forward Email @ https://forwardemail.net", + "dev": true, + "license": "MIT", + "dependencies": { + "methods": "^1.1.2", + "superagent": "^8.1.2" + }, + "engines": { + "node": ">=6.4.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", + "license": "MIT" + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", + "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/to-buffer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/toml": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", + "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==", + "license": "MIT" + }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "license": "ISC", + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-jest": { + "version": "29.4.12", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.12.tgz", + "integrity": "sha512-Ov6ClY53Fflh6BGAnY2DlTq1hYDrTycz2PVTXBWFW2CU+9zrEqAp9fWdGXl42EXO5RLSFAcAZ2JFKbP+zBTFfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bs-logger": "^0.2.6", + "fast-json-stable-stringify": "^2.1.0", + "handlebars": "^4.7.9", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.8.5", + "type-fest": "^4.41.0", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0 || ^30.0.0", + "@jest/types": "^29.0.0 || ^30.0.0", + "babel-jest": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-util": "^29.0.0 || ^30.0.0", + "typescript": ">=4.3 <7" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jest-util": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=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/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "license": "Unlicense" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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.28", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.28.tgz", + "integrity": "sha512-6GH7wXhtfq2D33ZuRXYwIsl/qM5685WZcODZb7noOOcRMteM9KF2x2ap3H0EBjnSV0VO4gNAfJT5Ukp0PkOlvg==", + "license": "MIT", + "dependencies": { + "@sqltools/formatter": "^1.2.5", + "ansis": "^4.2.0", + "app-root-path": "^3.1.0", + "buffer": "^6.0.3", + "dayjs": "^1.11.19", + "debug": "^4.4.3", + "dedent": "^1.7.0", + "dotenv": "^16.6.1", + "glob": "^10.5.0", + "reflect-metadata": "^0.2.2", + "sha.js": "^2.4.12", + "sql-highlight": "^6.1.0", + "tslib": "^2.8.1", + "uuid": "^11.1.0", + "yargs": "^17.7.2" + }, + "bin": { + "typeorm": "cli.js", + "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js", + "typeorm-ts-node-esm": "cli-ts-node-esm.js" + }, + "engines": { + "node": ">=16.13.0" + }, + "funding": { + "url": "https://opencollective.com/typeorm" + }, + "peerDependencies": { + "@google-cloud/spanner": "^5.18.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "@sap/hana-client": "^2.14.22", + "better-sqlite3": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0", + "ioredis": "^5.0.4", + "mongodb": "^5.8.0 || ^6.0.0", + "mssql": "^9.1.1 || ^10.0.0 || ^11.0.0 || ^12.0.0", + "mysql2": "^2.2.5 || ^3.0.1", + "oracledb": "^6.3.0", + "pg": "^8.5.1", + "pg-native": "^3.0.0", + "pg-query-stream": "^4.0.0", + "redis": "^3.1.1 || ^4.0.0 || ^5.0.14", + "sql.js": "^1.4.0", + "sqlite3": "^5.0.3", + "ts-node": "^10.7.0", + "typeorm-aurora-data-api-driver": "^2.0.0 || ^3.0.0" + }, + "peerDependenciesMeta": { + "@google-cloud/spanner": { + "optional": true + }, + "@sap/hana-client": { + "optional": true + }, + "better-sqlite3": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "mongodb": { + "optional": true + }, + "mssql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "oracledb": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "pg-query-stream": { + "optional": true + }, + "redis": { + "optional": true + }, + "sql.js": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "ts-node": { + "optional": true + }, + "typeorm-aurora-data-api-driver": { + "optional": true + } + } + }, + "node_modules/typeorm/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typeorm/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typeorm/node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "license": "ISC", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/urijs": { + "version": "1.19.11", + "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz", + "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==", + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/winston": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.19.0.tgz", + "integrity": "sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==", + "license": "MIT", + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.8", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.7.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.9.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz", + "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", + "license": "MIT", + "dependencies": { + "logform": "^2.7.0", + "readable-stream": "^3.6.2", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json index 3645e5d..e7de640 100644 --- a/package.json +++ b/package.json @@ -97,6 +97,6 @@ "ts-jest": "^29.4.12", "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", - "typescript": "^5.3.3" + "typescript": "^5.9.3" } } diff --git a/src/app.ts b/src/app.ts index c35e5c1..f5bf8db 100644 --- a/src/app.ts +++ b/src/app.ts @@ -109,7 +109,7 @@ export function createApp({ cors({ origin: http?.corsAllowedOrigins ?? true, credentials: http?.corsAllowCredentials ?? false, - }), + }) ); if (kycService) { @@ -122,28 +122,26 @@ export function createApp({ // FORCE RATE LIMITER (tests depend on it) if (http?.rateLimit?.enabled !== false) { - applyRateLimiters(app, appLogger, { - global: http?.rateLimit - ? { - windowMs: http.rateLimit.windowMs ?? 60_000, - max: http.rateLimit.max ?? 100, - } - : undefined, -}); -} + applyRateLimiters(app, appLogger, { + global: http?.rateLimit + ? { + windowMs: http.rateLimit.windowMs ?? 60_000, + max: http.rateLimit.max ?? 100, + } + : undefined, + }); + } app.use( createRequestObservabilityMiddleware({ logger: appLogger, metricsEnabled, metricsRegistry, - }), + }) ); app.get("/health", (req, res) => { const requestId = - (req.headers["x-request-id"] as string) || - (req as RequestWithId).requestId || - "unknown"; + (req.headers["x-request-id"] as string) || (req as RequestWithId).requestId || "unknown"; res.setHeader("x-request-id", requestId); @@ -212,7 +210,7 @@ export function createApp({ authService, contractGuardService, contractId: pauseGuardContractId, - }), + }) ); } @@ -223,7 +221,7 @@ export function createApp({ settlementService, contractGuardService, contractId: pauseGuardContractId, - }), + }) ); } @@ -234,7 +232,7 @@ export function createApp({ if (config?.admin?.ipWhitelist?.length) { app.use( "/api/v1/admin", - createAdminRouter({ dataSource, allowedCidrs: config.admin.ipWhitelist, invoiceService }), + createAdminRouter({ dataSource, allowedCidrs: config.admin.ipWhitelist, invoiceService }) ); } diff --git a/src/config/data-source.ts b/src/config/data-source.ts index 7ed0800..4f982cb 100644 --- a/src/config/data-source.ts +++ b/src/config/data-source.ts @@ -30,6 +30,8 @@ export async function initializeDataSource(): Promise { } } catch (error) { logger.error("Failed to initialize DataSource", { error }); - throw new Error(`DataSource initialization failed: ${error instanceof Error ? error.message : String(error)}`); + throw new Error( + `DataSource initialization failed: ${error instanceof Error ? error.message : String(error)}` + ); } } diff --git a/src/config/database.ts b/src/config/database.ts index 4711a9c..1ae49b2 100644 --- a/src/config/database.ts +++ b/src/config/database.ts @@ -20,7 +20,9 @@ let lastPoolErrorLog = 0; * Logs a warn when utilisation exceeds 80% and error at 100%. * Each log is emitted at most once per 30 seconds. */ -export function startPoolMonitor(getPool: () => { totalCount: number; idleCount: number; waitingCount: number } | null): void { +export function startPoolMonitor( + getPool: () => { totalCount: number; idleCount: number; waitingCount: number } | null +): void { setInterval(() => { const pool = getPool(); if (!pool) return; @@ -85,9 +87,17 @@ if (!isDevelopment) { startPoolMonitor(() => { try { // TypeORM exposes the underlying pg pool via driver.master/slave - const pool = (dataSource.driver as unknown as { master?: { totalCount: number; idleCount: number; waitingCount: number } })?.master; + const pool = ( + dataSource.driver as unknown as { + master?: { totalCount: number; idleCount: number; waitingCount: number }; + } + )?.master; if (pool && typeof pool.totalCount === "number") { - return { totalCount: pool.totalCount, idleCount: pool.idleCount, waitingCount: pool.waitingCount }; + return { + totalCount: pool.totalCount, + idleCount: pool.idleCount, + waitingCount: pool.waitingCount, + }; } } catch { // Ignore — pool not yet initialised diff --git a/src/config/env.ts b/src/config/env.ts index c15f04f..2805fd7 100644 --- a/src/config/env.ts +++ b/src/config/env.ts @@ -68,7 +68,6 @@ export interface AppConfig { }; } - // ---------------- DEFAULTS ---------------- const DEFAULT_PORT = 3000; @@ -97,7 +96,6 @@ const DEFAULT_IPFS_ALLOWED_MIME_TYPES = [ const DEFAULT_IPFS_UPLOAD_RATE_LIMIT_WINDOW_MS = 15 * 60 * 1000; const DEFAULT_IPFS_UPLOAD_RATE_LIMIT_MAX_UPLOADS = 10; - // ---------------- HELPERS ---------------- function parsePort(value?: string): number { @@ -130,7 +128,10 @@ function parseBoolean(value: string | undefined, fallback: boolean, name: string function parseCsv(value?: string): string[] { if (!value) return []; - return value.split(",").map(v => v.trim()).filter(Boolean); + return value + .split(",") + .map((v) => v.trim()) + .filter(Boolean); } function parseTrustProxy(value?: string): boolean | number | string { @@ -166,7 +167,6 @@ function requireString(value: string | undefined, name: string): string { return value; } - // ---------------- MAIN CONFIG ---------------- export function getConfig(): AppConfig { @@ -216,11 +216,7 @@ export function getConfig(): AppConfig { 60000, "RATE_LIMIT_WINDOW_MS" ), - max: parsePositiveInteger( - process.env.RATE_LIMIT_MAX, - 100, - "RATE_LIMIT_MAX" - ), + max: parsePositiveInteger(process.env.RATE_LIMIT_MAX, 100, "RATE_LIMIT_MAX"), }, }, diff --git a/src/config/stellar.ts b/src/config/stellar.ts index 960cc84..ec57632 100644 --- a/src/config/stellar.ts +++ b/src/config/stellar.ts @@ -52,25 +52,21 @@ export function getSorobanConfig(): SorobanConfig { "https://soroban-testnet.stellar.org"; const networkPassphrase = - process.env.STELLAR_NETWORK_PASSPHRASE ?? - "Test SDF Network ; September 2015"; + process.env.STELLAR_NETWORK_PASSPHRASE ?? "Test SDF Network ; September 2015"; const escrowContractId = process.env.SOROBAN_ESCROW_CONTRACT_ID ?? process.env.ESCROW_CONTRACT_ID ?? "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM"; - const tokenContractId = - process.env.SOROBAN_TOKEN_CONTRACT_ID ?? - process.env.TOKEN_CONTRACT_ID; + const tokenContractId = process.env.SOROBAN_TOKEN_CONTRACT_ID ?? process.env.TOKEN_CONTRACT_ID; const paymentDistributorContractId = process.env.SOROBAN_PAYMENT_DISTRIBUTOR_CONTRACT_ID ?? process.env.PAYMENT_DISTRIBUTOR_CONTRACT_ID; const platformSecretKey = - process.env.STELLAR_PLATFORM_SECRET_KEY ?? - process.env.PLATFORM_SECRET_KEY; + process.env.STELLAR_PLATFORM_SECRET_KEY ?? process.env.PLATFORM_SECRET_KEY; const platformFeeRecipient = process.env.PLATFORM_FEE_RECIPIENT; const platformFeeBps = Number(process.env.PLATFORM_FEE_BPS ?? "0"); if (!Number.isInteger(platformFeeBps) || platformFeeBps < 0 || platformFeeBps > 10_000) { @@ -92,29 +88,20 @@ export function getSorobanConfig(): SorobanConfig { export function getPaymentVerificationConfig(): PaymentVerificationConfig { return { horizonUrl: requireEnv(process.env.STELLAR_HORIZON_URL, "STELLAR_HORIZON_URL"), - usdcAssetCode: requireEnv( - process.env.STELLAR_USDC_ASSET_CODE, - "STELLAR_USDC_ASSET_CODE", - ), - usdcAssetIssuer: requireEnv( - process.env.STELLAR_USDC_ASSET_ISSUER, - "STELLAR_USDC_ASSET_ISSUER", - ), - escrowPublicKey: requireEnv( - process.env.STELLAR_ESCROW_PUBLIC_KEY, - "STELLAR_ESCROW_PUBLIC_KEY", - ), + usdcAssetCode: requireEnv(process.env.STELLAR_USDC_ASSET_CODE, "STELLAR_USDC_ASSET_CODE"), + usdcAssetIssuer: requireEnv(process.env.STELLAR_USDC_ASSET_ISSUER, "STELLAR_USDC_ASSET_ISSUER"), + escrowPublicKey: requireEnv(process.env.STELLAR_ESCROW_PUBLIC_KEY, "STELLAR_ESCROW_PUBLIC_KEY"), allowedAmountDelta: process.env.STELLAR_VERIFY_ALLOWED_AMOUNT_DELTA ?? DEFAULT_ALLOWED_AMOUNT_DELTA, retryAttempts: parsePositiveInteger( process.env.STELLAR_VERIFY_RETRY_ATTEMPTS, DEFAULT_RETRY_ATTEMPTS, - "STELLAR_VERIFY_RETRY_ATTEMPTS", + "STELLAR_VERIFY_RETRY_ATTEMPTS" ), retryBaseDelayMs: parsePositiveInteger( process.env.STELLAR_VERIFY_RETRY_BASE_DELAY_MS, DEFAULT_RETRY_BASE_DELAY_MS, - "STELLAR_VERIFY_RETRY_BASE_DELAY_MS", + "STELLAR_VERIFY_RETRY_BASE_DELAY_MS" ), }; } diff --git a/src/controllers/auth.controller.ts b/src/controllers/auth.controller.ts index d2623a1..c69174a 100644 --- a/src/controllers/auth.controller.ts +++ b/src/controllers/auth.controller.ts @@ -6,10 +6,7 @@ import type { AuthenticatedRequest } from "../types/auth"; export function createAuthController(authService: AuthService) { return { // Request challenge for signing - challenge: async ( - req: AuthenticatedRequest, - res: Response - ): Promise => { + challenge: async (req: AuthenticatedRequest, res: Response): Promise => { const challenge = await authService.createChallenge(req.body.publicKey); res.status(201).json({ challenge }); }, @@ -20,7 +17,8 @@ export function createAuthController(authService: AuthService) { res: Response ): Promise => { const forwarded = req.headers["x-forwarded-for"]; - const ipAddress = (Array.isArray(forwarded) ? forwarded[0] : forwarded?.split(",")[0]?.trim()) ?? req.ip; + const ipAddress = + (Array.isArray(forwarded) ? forwarded[0] : forwarded?.split(",")[0]?.trim()) ?? req.ip; const session = await authService.verifyChallenge({ ...req.body, ipAddress }); res.status(200).json(session); }, @@ -36,4 +34,4 @@ export function createAuthController(authService: AuthService) { res.status(200).json({ user }); }, }; -} \ No newline at end of file +} diff --git a/src/controllers/investment.controller.ts b/src/controllers/investment.controller.ts index f9497b8..e4304e3 100644 --- a/src/controllers/investment.controller.ts +++ b/src/controllers/investment.controller.ts @@ -39,7 +39,8 @@ export class InvestmentController { data: investment, }); } catch (err: unknown) { - const statusCode = (err as { status?: number }).status || (err as { statusCode?: number }).statusCode || 400; + const statusCode = + (err as { status?: number }).status || (err as { statusCode?: number }).statusCode || 400; return res.status(statusCode).json({ error: { code: (err as { code?: string }).code || "INTERNAL_ERROR", @@ -63,7 +64,8 @@ export class InvestmentController { data: dashboard, }); } catch (err: unknown) { - const statusCode = (err as { status?: number }).status || (err as { statusCode?: number }).statusCode || 500; + const statusCode = + (err as { status?: number }).status || (err as { statusCode?: number }).statusCode || 500; return res.status(statusCode).json({ error: { code: (err as { code?: string }).code || "INTERNAL_ERROR", @@ -87,7 +89,8 @@ export class InvestmentController { data: analytics, }); } catch (err: unknown) { - const statusCode = (err as { status?: number }).status || (err as { statusCode?: number }).statusCode || 500; + const statusCode = + (err as { status?: number }).status || (err as { statusCode?: number }).statusCode || 500; return res.status(statusCode).json({ error: { code: (err as { code?: string }).code || "INTERNAL_ERROR", diff --git a/src/controllers/invoice.controller.ts b/src/controllers/invoice.controller.ts index d7286cb..9ccf7e1 100644 --- a/src/controllers/invoice.controller.ts +++ b/src/controllers/invoice.controller.ts @@ -63,22 +63,15 @@ export function createInvoiceController(invoiceService: InvoiceService) { async createInvoice( req: CreateInvoiceRequest, res: Response, - next: NextFunction, + next: NextFunction ): Promise { try { if (!req.user) { throw new HttpError(401, "Authentication required"); } - const { - invoiceNumber, - customerName, - amount, - discountRate, - dueDate, - ipfsHash, - riskScore, - } = req.body; + const { invoiceNumber, customerName, amount, discountRate, dueDate, ipfsHash, riskScore } = + req.body; const result = await invoiceService.createInvoice({ sellerId: req.user.id, @@ -105,11 +98,7 @@ export function createInvoiceController(invoiceService: InvoiceService) { } }, - async getInvoices( - req: GetInvoicesRequest, - res: Response, - next: NextFunction, - ): Promise { + async getInvoices(req: GetInvoicesRequest, res: Response, next: NextFunction): Promise { try { if (!req.user) { throw new HttpError(401, "Authentication required"); @@ -154,7 +143,7 @@ export function createInvoiceController(invoiceService: InvoiceService) { async getInvoice( req: Request & { params: { id: string } }, res: Response, - next: NextFunction, + next: NextFunction ): Promise { try { const authReq = req as AuthenticatedRequest; @@ -165,10 +154,7 @@ export function createInvoiceController(invoiceService: InvoiceService) { const { id } = req.params; try { - const result = await invoiceService.getInvoiceById( - id, - authReq.user.id, - ); + const result = await invoiceService.getInvoiceById(id, authReq.user.id); if (!result) { throw new HttpError(404, "Invoice not found"); @@ -198,7 +184,7 @@ export function createInvoiceController(invoiceService: InvoiceService) { async updateInvoice( req: UpdateInvoiceRequest, res: Response, - next: NextFunction, + next: NextFunction ): Promise { try { if (!req.user) { @@ -206,8 +192,7 @@ export function createInvoiceController(invoiceService: InvoiceService) { } const { id } = req.params; - const { customerName, amount, discountRate, dueDate, riskScore } = - req.body; + const { customerName, amount, discountRate, dueDate, riskScore } = req.body; const result = await invoiceService.updateInvoice({ sellerId: req.user.id, @@ -241,7 +226,7 @@ export function createInvoiceController(invoiceService: InvoiceService) { async deleteInvoice( req: Request & { params: { id: string } }, res: Response, - next: NextFunction, + next: NextFunction ): Promise { try { const authReq = req as AuthenticatedRequest; @@ -272,7 +257,7 @@ export function createInvoiceController(invoiceService: InvoiceService) { async publishInvoice( req: PublishInvoiceRequest, res: Response, - next: NextFunction, + next: NextFunction ): Promise { try { if (!req.user) { @@ -308,7 +293,7 @@ export function createInvoiceController(invoiceService: InvoiceService) { async batchPublishInvoices( req: BatchPublishInvoicesRequest, res: Response, - next: NextFunction, + next: NextFunction ): Promise { try { if (!req.user) { @@ -340,7 +325,7 @@ export function createInvoiceController(invoiceService: InvoiceService) { async uploadDocument( req: UploadDocumentRequest, res: Response, - next: NextFunction, + next: NextFunction ): Promise { try { if (!req.user) { @@ -379,7 +364,7 @@ export function createInvoiceController(invoiceService: InvoiceService) { async getInvoiceTokenHolders( req: Request & { params: { id: string } }, res: Response, - next: NextFunction, + next: NextFunction ): Promise { try { const { id } = req.params; @@ -403,7 +388,7 @@ export function createInvoiceController(invoiceService: InvoiceService) { async getInvoiceEscrowStatus( req: Request & { params: { id: string } }, res: Response, - next: NextFunction, + next: NextFunction ): Promise { try { const { id } = req.params; @@ -424,11 +409,7 @@ export function createInvoiceController(invoiceService: InvoiceService) { } }, - async calculateTerms( - req: Request, - res: Response, - next: NextFunction, - ): Promise { + async calculateTerms(req: Request, res: Response, next: NextFunction): Promise { try { const { faceValue, dueDate, discountBps, platformFeeBps, referenceDate } = req.body; @@ -446,9 +427,7 @@ export function createInvoiceController(invoiceService: InvoiceService) { }); } catch (error) { const message = - error instanceof Error - ? error.message - : "Failed to calculate invoice terms"; + error instanceof Error ? error.message : "Failed to calculate invoice terms"; next(new HttpError(400, message)); } }, diff --git a/src/controllers/kyc.controller.ts b/src/controllers/kyc.controller.ts index e2d0b20..28248dc 100644 --- a/src/controllers/kyc.controller.ts +++ b/src/controllers/kyc.controller.ts @@ -11,17 +11,23 @@ export function createKycController(service: KycService) { }, webhook: async (req: Request, res: Response) => { if (!Buffer.isBuffer(req.body)) { - return res.status(400).json({ error: { code: "RAW_BODY_REQUIRED", message: "Raw webhook body required" } }); + return res + .status(400) + .json({ error: { code: "RAW_BODY_REQUIRED", message: "Raw webhook body required" } }); } const rawBody = req.body; if (!service.verifyWebhookSignature(rawBody, req.header("x-provider-signature"))) { - return res.status(401).json({ error: { code: "INVALID_WEBHOOK_SIGNATURE", message: "Invalid webhook signature" } }); + return res.status(401).json({ + error: { code: "INVALID_WEBHOOK_SIGNATURE", message: "Invalid webhook signature" }, + }); } let payload: unknown; try { payload = JSON.parse(rawBody.toString("utf8")); } catch { - return res.status(400).json({ error: { code: "INVALID_WEBHOOK_PAYLOAD", message: "Invalid JSON payload" } }); + return res + .status(400) + .json({ error: { code: "INVALID_WEBHOOK_PAYLOAD", message: "Invalid JSON payload" } }); } await service.processWebhook(payload as Parameters[0]); return res.status(204).send(); diff --git a/src/controllers/marketplace.controller.ts b/src/controllers/marketplace.controller.ts index bdcb512..75f59b6 100644 --- a/src/controllers/marketplace.controller.ts +++ b/src/controllers/marketplace.controller.ts @@ -1,6 +1,10 @@ import type { Request, Response, NextFunction } from "express"; import Joi from "joi"; -import type { MarketplaceService, MarketplaceFilters, PaginationOptions } from "../services/marketplace.service"; +import type { + MarketplaceService, + MarketplaceFilters, + PaginationOptions, +} from "../services/marketplace.service"; import { InvoiceStatus } from "../types/enums"; import { HttpError } from "../utils/http-error"; import { ServiceError } from "../utils/service-error"; @@ -8,10 +12,12 @@ import { ServiceError } from "../utils/service-error"; const getInvoicesSchema = Joi.object({ page: Joi.number().integer().min(1).default(1), limit: Joi.number().integer().min(1).max(100).default(20), - status: Joi.alternatives().try( - Joi.string().valid(...Object.values(InvoiceStatus)), - Joi.array().items(Joi.string().valid(...Object.values(InvoiceStatus))), - ).optional(), + status: Joi.alternatives() + .try( + Joi.string().valid(...Object.values(InvoiceStatus)), + Joi.array().items(Joi.string().valid(...Object.values(InvoiceStatus))) + ) + .optional(), dueBefore: Joi.date().iso().optional(), minAmount: Joi.number().min(0).optional(), maxAmount: Joi.number().min(0).optional(), @@ -35,11 +41,7 @@ export interface GetInvoicesRequest extends Request { export function createMarketplaceController(marketplaceService: MarketplaceService) { return { - async getInvoices( - req: GetInvoicesRequest, - res: Response, - next: NextFunction, - ): Promise { + async getInvoices(req: GetInvoicesRequest, res: Response, next: NextFunction): Promise { try { // Validate query parameters const { error, value } = getInvoicesSchema.validate(req.query, { @@ -53,7 +55,11 @@ export function createMarketplaceController(marketplaceService: MarketplaceServi // Parse and normalize filters const filters: MarketplaceFilters = { - status: Array.isArray(value.status) ? value.status : value.status ? [value.status] : undefined, + status: Array.isArray(value.status) + ? value.status + : value.status + ? [value.status] + : undefined, dueBefore: value.dueBefore, minAmount: value.minAmount, maxAmount: value.maxAmount, @@ -91,4 +97,4 @@ export function createMarketplaceController(marketplaceService: MarketplaceServi } }, }; -} \ No newline at end of file +} diff --git a/src/controllers/notification.controller.ts b/src/controllers/notification.controller.ts index 14da7e8..2c0ecc5 100644 --- a/src/controllers/notification.controller.ts +++ b/src/controllers/notification.controller.ts @@ -2,9 +2,7 @@ import type { Request, Response } from "express"; import type { NotificationService } from "../services/notification.service"; import { NotificationType } from "../types/enums"; -export function createNotificationController( - notificationService: NotificationService, -) { +export function createNotificationController(notificationService: NotificationService) { return { list: async (req: Request, res: Response): Promise => { const userId = req.user!.id; @@ -12,7 +10,7 @@ export function createNotificationController( const page = Math.max(1, parseInt((req.query.page as string) ?? "1", 10) || 1); const limit = Math.min( 100, - Math.max(1, parseInt((req.query.limit as string) ?? "20", 10) || 20), + Math.max(1, parseInt((req.query.limit as string) ?? "20", 10) || 20) ); const readParam = req.query.read as string | undefined; @@ -26,8 +24,7 @@ export function createNotificationController( ? (typeParam as NotificationType) : undefined; - const sortOrder = - (req.query.sort as string) === "asc" ? ("asc" as const) : ("desc" as const); + const sortOrder = (req.query.sort as string) === "asc" ? ("asc" as const) : ("desc" as const); const cursor = req.query.cursor as string | undefined; const result = await notificationService.listNotifications({ diff --git a/src/controllers/settlement.controller.ts b/src/controllers/settlement.controller.ts index 8477564..f0f7f31 100644 --- a/src/controllers/settlement.controller.ts +++ b/src/controllers/settlement.controller.ts @@ -35,9 +35,7 @@ export class SettlementController { }); } catch (err: unknown) { const statusCode = - (err as { statusCode?: number }).statusCode || - (err as { status?: number }).status || - 400; + (err as { statusCode?: number }).statusCode || (err as { status?: number }).status || 400; return res.status(statusCode).json({ error: { code: (err as { code?: string }).code || "INTERNAL_ERROR", diff --git a/src/controllers/user.controller.ts b/src/controllers/user.controller.ts index 013878d..6b824ab 100644 --- a/src/controllers/user.controller.ts +++ b/src/controllers/user.controller.ts @@ -7,9 +7,17 @@ import { isValidStellarPublicKey } from "../utils/stellar-address.utils"; export interface UserRepositoryContract { findById(id: string): Promise; findByStellarAddress(address: string): Promise; - findAll(options?: { skip?: number; take?: number }): Promise; - count?(): Promise; - save(user: Partial): Promise; + findByEmail(email: string): Promise; + findAll(options?: { + skip?: number; + take?: number; + cursor?: string; + order?: "ASC" | "DESC"; + }): Promise; + count(options?: { cursor?: string }): Promise; + save( + user: Partial + ): Promise; } export interface UserControllerDeps { @@ -17,6 +25,9 @@ export interface UserControllerDeps { logger?: AppLogger; } +const MAX_CURSOR_LIMIT = 100; +const DEFAULT_CURSOR_LIMIT = 20; + function sanitizeString(value: unknown, maxLength = 255): string | null { if (typeof value !== "string") return null; const trimmed = value.trim(); @@ -24,6 +35,14 @@ function sanitizeString(value: unknown, maxLength = 255): string | null { return trimmed.slice(0, maxLength); } +function sanitizeCursor(value: unknown): string | null { + if (typeof value !== "string") return null; + const trimmed = value.trim(); + if (!trimmed) return null; + if (!/^[0-9a-fA-F-]{36}$/.test(trimmed)) return null; + return trimmed; +} + function toPublicUser(user: import("../models/User.model").User) { return { id: user.id, @@ -37,16 +56,28 @@ function toPublicUser(user: import("../models/User.model").User) { }; } +function getRequestId(req: AuthenticatedRequest): string { + return ( + (req.headers["x-request-id"] as string) || + ((req as unknown as Record).requestId as string) || + "unknown" + ); +} + +function setCacheHeaders(res: Response, user: import("../models/User.model").User): void { + const etag = `W/"${user.id}-${user.updatedAt.getTime()}"`; + res.setHeader("ETag", etag); + res.setHeader("Last-Modified", user.updatedAt.toUTCString()); + res.setHeader("Cache-Control", "private, max-age=60"); +} + export function createUserController(deps: UserControllerDeps) { const userRepository = deps.userRepository; const appLogger = deps.logger ?? defaultLogger; return { - async getProfile( - req: AuthenticatedRequest, - res: Response, - next: NextFunction, - ): Promise { + async getProfile(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise { + const requestId = getRequestId(req); try { if (!req.user?.id) { throw new HttpError(401, "Authentication required"); @@ -55,7 +86,8 @@ export function createUserController(deps: UserControllerDeps) { if (!user) { throw new HttpError(404, "User not found"); } - res.status(200).json({ success: true, data: toPublicUser(user) }); + setCacheHeaders(res, user); + res.status(200).json({ success: true, data: toPublicUser(user), requestId }); } catch (error) { if (error instanceof HttpError || error instanceof AppError) { next(error); @@ -64,6 +96,7 @@ export function createUserController(deps: UserControllerDeps) { appLogger.error("Failed to fetch user profile", { error: error instanceof Error ? error.message : String(error), userId: req.user?.id, + requestId, }); next(new AppError(500, "Failed to fetch profile", "PROFILE_FETCH_FAILED")); } @@ -72,8 +105,9 @@ export function createUserController(deps: UserControllerDeps) { async getUserById( req: AuthenticatedRequest & { params: { id: string } }, res: Response, - next: NextFunction, + next: NextFunction ): Promise { + const requestId = getRequestId(req); try { if (!req.user) { throw new HttpError(401, "Authentication required"); @@ -82,12 +116,12 @@ export function createUserController(deps: UserControllerDeps) { if (!rawId) { throw new HttpError(400, "Invalid user id"); } - // Prevent enumeration via timing-safe consistent behavior: still 404 on not found const user = await userRepository.findById(rawId); if (!user) { throw new HttpError(404, "User not found"); } - res.status(200).json({ success: true, data: toPublicUser(user) }); + setCacheHeaders(res, user); + res.status(200).json({ success: true, data: toPublicUser(user), requestId }); } catch (error) { if (error instanceof HttpError || error instanceof AppError) { next(error); @@ -96,6 +130,7 @@ export function createUserController(deps: UserControllerDeps) { appLogger.error("Failed to fetch user by id", { error: error instanceof Error ? error.message : String(error), params: req.params, + requestId, }); next(new AppError(500, "Failed to fetch user", "USER_FETCH_FAILED")); } @@ -104,8 +139,9 @@ export function createUserController(deps: UserControllerDeps) { async updateProfile( req: AuthenticatedRequest, res: Response, - next: NextFunction, + next: NextFunction ): Promise { + const requestId = getRequestId(req); try { if (!req.user?.id) { throw new HttpError(401, "Authentication required"); @@ -119,6 +155,10 @@ export function createUserController(deps: UserControllerDeps) { if (!emailRegex.test(email)) { throw new HttpError(400, "Invalid email format"); } + const existingEmail = await userRepository.findByEmail(email); + if (existingEmail && existingEmail.id !== req.user.id) { + throw new HttpError(409, "Email already in use"); + } } if (stellarAddressRaw !== null && !isValidStellarPublicKey(stellarAddressRaw)) { @@ -138,15 +178,16 @@ export function createUserController(deps: UserControllerDeps) { if (email !== null) patch.email = email; if (stellarAddressRaw !== null) patch.stellarAddress = stellarAddressRaw; - // Use immutable update pattern: create new object const updated = await userRepository.save({ ...existing, ...patch }); appLogger.info("User profile updated", { userId: req.user.id, updatedFields: Object.keys(patch), + requestId, }); - res.status(200).json({ success: true, data: toPublicUser(updated) }); + setCacheHeaders(res, updated); + res.status(200).json({ success: true, data: toPublicUser(updated), requestId }); } catch (error) { if (error instanceof HttpError || error instanceof AppError) { next(error); @@ -155,41 +196,97 @@ export function createUserController(deps: UserControllerDeps) { appLogger.error("Failed to update user profile", { error: error instanceof Error ? error.message : String(error), userId: req.user?.id, + requestId, }); next(new AppError(500, "Failed to update profile", "PROFILE_UPDATE_FAILED")); } }, async listUsers( - req: AuthenticatedRequest & { query: { page?: string; limit?: string } }, + req: AuthenticatedRequest & { + query: { page?: string; limit?: string; cursor?: string; order?: string }; + }, res: Response, - next: NextFunction, + next: NextFunction ): Promise { + const requestId = getRequestId(req); try { if (!req.user) { throw new HttpError(401, "Authentication required"); } - // Backward-compatible pagination with sanitized bounds - const page = Math.min(Math.max(Number(req.query.page) || 1, 1), 1000); - const limit = Math.min(Math.max(Number(req.query.limit) || 20, 1), 100); + const useCursor = typeof req.query.cursor === "string" && req.query.cursor.length > 0; + let cursor: string | null = null; + let limit = DEFAULT_CURSOR_LIMIT; + let order: "ASC" | "DESC" = "DESC"; + + if (useCursor) { + cursor = sanitizeCursor(req.query.cursor); + if (!cursor) { + throw new HttpError(400, "Invalid cursor format"); + } + limit = Math.min( + Math.max(Number(req.query.limit) || DEFAULT_CURSOR_LIMIT, 1), + MAX_CURSOR_LIMIT + ); + if (req.query.order === "asc" || req.query.order === "ASC") { + order = "ASC"; + } + } else { + const _page = Math.min(Math.max(Number(req.query.page) || 1, 1), 1000); + limit = Math.min(Math.max(Number(req.query.limit) || 20, 1), 100); + } - let users: import("../models/User.model").User[]; + let users: import("../models/User.model").User[] = []; let total = 0; + let nextCursor: string | undefined = undefined; try { - users = await userRepository.findAll({ skip: (page - 1) * limit, take: limit }); - total = userRepository.count ? await userRepository.count() : users.length; + if (useCursor) { + users = await userRepository.findAll({ + cursor: cursor ?? undefined, + take: limit + 1, + order, + }); + total = await userRepository.count({ cursor: cursor ?? undefined }); + if (users.length > limit) { + const nextUser = users.pop(); + nextCursor = nextUser!.id; + } + } else { + const page = Math.min(Math.max(Number(req.query.page) || 1, 1), 1000); + const skip = (page - 1) * limit; + const [fetchedUsers, fetchedTotal] = await Promise.all([ + userRepository.findAll({ skip, take: limit }), + userRepository.count ? userRepository.count() : Promise.resolve(0), + ]); + users = fetchedUsers; + total = fetchedTotal; + } } catch (error) { - appLogger.error("Failed to list users", { error }); + appLogger.error("Failed to list users", { error, requestId }); throw new AppError(500, "Failed to list users", "USER_LIST_FAILED"); } - res.status(200).json({ + const response: { + success: boolean; + data: ReturnType[]; + requestId: string; + meta?: Record; + } = { success: true, data: users.map(toPublicUser), - meta: { total, page, limit, totalPages: Math.ceil(total / limit) }, - }); + requestId, + }; + + if (useCursor) { + response.meta = { total, limit, nextCursor }; + } else { + const page = Math.min(Math.max(Number(req.query.page) || 1, 1), 1000); + response.meta = { total, page, limit, totalPages: Math.ceil(total / limit) }; + } + + res.status(200).json(response); } catch (error) { if (error instanceof HttpError || error instanceof AppError) { next(error); @@ -197,6 +294,7 @@ export function createUserController(deps: UserControllerDeps) { } appLogger.error("Unhandled error in listUsers", { error: error instanceof Error ? error.message : String(error), + requestId, }); next(new AppError(500, "Processing failed", "USER_LIST_FAILED")); } diff --git a/src/entities/User.ts b/src/entities/User.ts index 765f68c..31d53fe 100644 --- a/src/entities/User.ts +++ b/src/entities/User.ts @@ -11,4 +11,4 @@ export class User { @Column({ type: "enum", enum: KYCStatus, default: KYCStatus.PENDING }) kycStatus!: KYCStatus; -} \ No newline at end of file +} diff --git a/src/index.ts b/src/index.ts index ee1be32..f803f19 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ import { createApp } from "./app"; import dataSource from "./config/database"; import { getConfig } from "./config/env"; import { logger } from "./observability/logger"; +import { MetricsRegistry } from "./observability/metrics"; import { createAuthService } from "./services/auth.service"; import { createNotificationService } from "./services/notification.service"; @@ -24,18 +25,25 @@ export async function bootstrap(): Promise<{ server: Server }> { await dataSource.initialize(); } - const authService = createAuthService(dataSource, config, logger); + const metricsRegistry = new MetricsRegistry(); + + const authService = createAuthService(dataSource, config, logger, metricsRegistry); const notificationService = createNotificationService(dataSource); const ipfsService = createIPFSService(config.ipfs, logger); const invoiceService = createInvoiceService(dataSource, ipfsService, notificationService); const investmentService = createInvestmentService(dataSource); const sorobanConfig = getSorobanConfig(); - const distributor = sorobanConfig.paymentDistributorContractId && sorobanConfig.platformSecretKey - ? new PaymentDistributorContractService({ ...sorobanConfig, contractId: sorobanConfig.paymentDistributorContractId }, logger) - : undefined; - const distributorConfig = distributor && sorobanConfig.platformFeeRecipient - ? { feeRecipient: sorobanConfig.platformFeeRecipient, feeBps: sorobanConfig.platformFeeBps } - : undefined; + const distributor = + sorobanConfig.paymentDistributorContractId && sorobanConfig.platformSecretKey + ? new PaymentDistributorContractService( + { ...sorobanConfig, contractId: sorobanConfig.paymentDistributorContractId }, + logger + ) + : undefined; + const distributorConfig = + distributor && sorobanConfig.platformFeeRecipient + ? { feeRecipient: sorobanConfig.platformFeeRecipient, feeBps: sorobanConfig.platformFeeBps } + : undefined; const settlementService = createSettlementService(dataSource, distributor, distributorConfig); const marketplaceService = createMarketplaceService(dataSource); const kycService = new KycService(dataSource, config.kyc.webhookSecret ?? "", logger); diff --git a/src/lib/auth-failure.ts b/src/lib/auth-failure.ts index d2b6d28..2959f9e 100644 --- a/src/lib/auth-failure.ts +++ b/src/lib/auth-failure.ts @@ -13,9 +13,7 @@ export interface AuthFailureDetails { failedAt: string; } -export function truncateWalletAddress( - address: string | null | undefined, -): string | null { +export function truncateWalletAddress(address: string | null | undefined): string | null { if (!address) { return null; } @@ -43,14 +41,12 @@ export function extractWalletFromUnverifiedToken(token?: string): string | null export function buildAuthFailureDetails( token: string | undefined, - reason: AuthFailureReason, + reason: AuthFailureReason ): { authFailure: AuthFailureDetails } { return { authFailure: { reason, - truncatedAddress: truncateWalletAddress( - extractWalletFromUnverifiedToken(token), - ), + truncatedAddress: truncateWalletAddress(extractWalletFromUnverifiedToken(token)), failedAt: new Date().toISOString(), }, }; diff --git a/src/lib/circuit-breaker.ts b/src/lib/circuit-breaker.ts new file mode 100644 index 0000000..3ea2cc0 --- /dev/null +++ b/src/lib/circuit-breaker.ts @@ -0,0 +1,83 @@ +export interface CircuitBreakerOptions { + failureThreshold: number; + successThreshold: number; + timeout: number; +} + +export interface CircuitBreakerState { + failures: number; + successes: number; + lastFailure: number; + state: "closed" | "open" | "half-open"; +} + +export class CircuitBreaker { + private state: CircuitBreakerState = { + failures: 0, + successes: 0, + lastFailure: 0, + state: "closed", + }; + + constructor(private readonly options: CircuitBreakerOptions) {} + + async execute(operation: () => Promise): Promise { + if (this.state.state === "open") { + if (Date.now() - this.state.lastFailure >= this.options.timeout) { + this.state.state = "half-open"; + } else { + throw new Error("Circuit breaker is open"); + } + } + + try { + const result = await operation(); + this.onSuccess(); + return result; + } catch (error) { + this.onFailure(); + throw error; + } + } + + private onSuccess(): void { + this.state.failures = 0; + if (this.state.state === "half-open") { + this.state.successes++; + if (this.state.successes >= this.options.successThreshold) { + this.state.state = "closed"; + this.state.successes = 0; + } + } + } + + private onFailure(): void { + this.state.failures++; + this.state.lastFailure = Date.now(); + this.state.successes = 0; + if (this.state.failures >= this.options.failureThreshold) { + this.state.state = "open"; + } + } + + getState(): CircuitBreakerState { + return { ...this.state }; + } + + reset(): void { + this.state = { + failures: 0, + successes: 0, + lastFailure: 0, + state: "closed", + }; + } +} + +export function createCircuitBreaker(options?: Partial): CircuitBreaker { + return new CircuitBreaker({ + failureThreshold: options?.failureThreshold ?? 5, + successThreshold: options?.successThreshold ?? 2, + timeout: options?.timeout ?? 30000, + }); +} diff --git a/src/lib/extract-wallet-from-token.ts b/src/lib/extract-wallet-from-token.ts index 36ec362..6093630 100644 --- a/src/lib/extract-wallet-from-token.ts +++ b/src/lib/extract-wallet-from-token.ts @@ -7,10 +7,7 @@ import jwt from "jsonwebtoken"; * Returns null for: missing token, expired token, invalid signature, * missing `sub` claim. Never throws. */ -export function extractWalletFromToken( - token: string | undefined, - secret: string, -): string | null { +export function extractWalletFromToken(token: string | undefined, secret: string): string | null { if (!token) { return null; } diff --git a/src/lib/investor-return.ts b/src/lib/investor-return.ts index a3527ce..3bf8483 100644 --- a/src/lib/investor-return.ts +++ b/src/lib/investor-return.ts @@ -7,7 +7,7 @@ export function computeInvestorReturn( investedAmount: bigint, totalFunded: bigint, - settledProceeds: bigint, + settledProceeds: bigint ): bigint { if (totalFunded <= 0n) { throw new RangeError("totalFunded must be greater than zero"); diff --git a/src/lib/invoice-validation.ts b/src/lib/invoice-validation.ts index 2c0bb2a..fac11a7 100644 --- a/src/lib/invoice-validation.ts +++ b/src/lib/invoice-validation.ts @@ -13,7 +13,10 @@ export interface PublishableInvoice { * publishing, so investors always have a full day of runway before the * invoice is due. */ -export function validateInvoiceForPublish(invoice: PublishableInvoice, now: Date = new Date()): void { +export function validateInvoiceForPublish( + invoice: PublishableInvoice, + now: Date = new Date() +): void { const leadTimeMs = invoice.dueDate.getTime() - now.getTime(); if (leadTimeMs < MIN_LEAD_TIME_MS) { @@ -21,7 +24,7 @@ export function validateInvoiceForPublish(invoice: PublishableInvoice, now: Date "invalid_due_date", "dueDate must be at least 24 hours in the future", 400, - { field: "dueDate" }, + { field: "dueDate" } ); } } diff --git a/src/lib/settlement-completion-log.ts b/src/lib/settlement-completion-log.ts index 176e9a8..203371b 100644 --- a/src/lib/settlement-completion-log.ts +++ b/src/lib/settlement-completion-log.ts @@ -16,7 +16,7 @@ export interface SettlementCompletionLogInput { */ export function logSettlementCompletion( logger: AppLogger, - input: SettlementCompletionLogInput, + input: SettlementCompletionLogInput ): void { logger.info("Settlement flow completed.", { invoice_id: input.invoiceId, diff --git a/src/lib/stellar-format.ts b/src/lib/stellar-format.ts index 6cbe7fc..4b25070 100644 --- a/src/lib/stellar-format.ts +++ b/src/lib/stellar-format.ts @@ -19,9 +19,10 @@ export function stroopsToXlm(stroops: bigint, decimals: number = STROOP_DECIMALS // Pad the stroop remainder out to full precision, then round/truncate to // the requested number of decimal places. const fullFraction = remainderStroops.toString().padStart(STROOP_DECIMALS, "0"); - const fraction = decimals <= STROOP_DECIMALS - ? fullFraction.slice(0, decimals) - : fullFraction.padEnd(decimals, "0"); + const fraction = + decimals <= STROOP_DECIMALS + ? fullFraction.slice(0, decimals) + : fullFraction.padEnd(decimals, "0"); const sign = negative ? "-" : ""; return decimals > 0 ? `${sign}${whole}.${fraction}` : `${sign}${whole}`; diff --git a/src/lib/validate-invoice-for-publish.ts b/src/lib/validate-invoice-for-publish.ts index ca26390..2528eba 100644 --- a/src/lib/validate-invoice-for-publish.ts +++ b/src/lib/validate-invoice-for-publish.ts @@ -35,7 +35,7 @@ export const MIN_FACE_VALUE_XLM = new Decimal("100"); */ export function validateFundingDeadline( dueDate: Date | string, - now: Date = new Date(), + now: Date = new Date() ): ValidationError | null { const deadline = new Date(dueDate); @@ -75,7 +75,10 @@ export function validateFundingDeadline( * `now` is threaded through to {@link validateFundingDeadline} for tests only; * production callers use the default server clock. */ -export function validateInvoiceForPublish(invoice: Invoice, now: Date = new Date()): ValidationError[] { +export function validateInvoiceForPublish( + invoice: Invoice, + now: Date = new Date() +): ValidationError[] { const errors: ValidationError[] = []; const faceValue = new Decimal(invoice.amount); diff --git a/src/middleware/auth.middleware.ts b/src/middleware/auth.middleware.ts index 102e130..ab00838 100644 --- a/src/middleware/auth.middleware.ts +++ b/src/middleware/auth.middleware.ts @@ -6,10 +6,7 @@ import type { AuthenticatedRequest } from "../types/auth"; import { AppError, HttpError } from "../utils/http-error"; import { UserType, KYCStatus } from "../types/enums"; -import { - buildAuthFailureDetails, - classifyJwtError, -} from "../lib/auth-failure"; +import { buildAuthFailureDetails, classifyJwtError } from "../lib/auth-failure"; interface AuthTokenPayload { sub: string; @@ -18,11 +15,7 @@ interface AuthTokenPayload { } export function createAuthMiddleware(authService: AuthService) { - return async ( - req: AuthenticatedRequest, - _res: Response, - next: NextFunction - ): Promise => { + return async (req: AuthenticatedRequest, _res: Response, next: NextFunction): Promise => { const authHeader = req.headers.authorization; if (!authHeader?.startsWith("Bearer ")) { @@ -30,8 +23,8 @@ export function createAuthMiddleware(authService: AuthService) { new HttpError( 401, "Authorization token is required.", - buildAuthFailureDetails(undefined, "missing_token"), - ), + buildAuthFailureDetails(undefined, "missing_token") + ) ); return; } @@ -51,18 +44,14 @@ export function createAuthMiddleware(authService: AuthService) { new HttpError( 401, "Invalid or expired token.", - buildAuthFailureDetails(token, classifyJwtError(error)), - ), + buildAuthFailureDetails(token, classifyJwtError(error)) + ) ); } }; } -export function authenticateJWT( - req: Request, - _res: Response, - next: NextFunction -): void { +export function authenticateJWT(req: Request, _res: Response, next: NextFunction): void { const authHeader = req.headers.authorization; if (!authHeader?.startsWith("Bearer ")) { @@ -70,8 +59,8 @@ export function authenticateJWT( new HttpError( 401, "Authorization token is required.", - buildAuthFailureDetails(undefined, "missing_token"), - ), + buildAuthFailureDetails(undefined, "missing_token") + ) ); return; } @@ -101,8 +90,8 @@ export function authenticateJWT( new HttpError( 401, "Invalid or expired token.", - buildAuthFailureDetails(token, classifyJwtError(error)), - ), + buildAuthFailureDetails(token, classifyJwtError(error)) + ) ); } } @@ -129,11 +118,7 @@ export function requireKYC(skipVerification = false) { }; } -export function checkKycVerified( - req: Request, - _res: Response, - next: NextFunction, -): void { +export function checkKycVerified(req: Request, _res: Response, next: NextFunction): void { const user = (req as AuthenticatedRequest).user; if (!user) { next(new HttpError(401, "Authentication required")); diff --git a/src/middleware/error.middleware.ts b/src/middleware/error.middleware.ts index 0d1c176..0e53a13 100644 --- a/src/middleware/error.middleware.ts +++ b/src/middleware/error.middleware.ts @@ -4,21 +4,12 @@ import type { AppLogger } from "../observability/logger"; import { AppError, HttpError } from "../utils/http-error"; import type { AuthFailureDetails } from "../lib/auth-failure"; -export function notFoundMiddleware( - _req: Request, - _res: Response, - next: NextFunction -) { +export function notFoundMiddleware(_req: Request, _res: Response, next: NextFunction) { next(new HttpError(404, "Route not found.")); } export function createErrorMiddleware(logger: AppLogger) { - return ( - error: unknown, - req: Request, - res: Response, - _next: NextFunction, - ): void => { + return (error: unknown, req: Request, res: Response, _next: NextFunction): void => { if (error instanceof AppError || error instanceof HttpError) { res.status(error.statusCode).json({ success: false, diff --git a/src/middleware/ip-whitelist.middleware.ts b/src/middleware/ip-whitelist.middleware.ts index 5c632d5..3e0236a 100644 --- a/src/middleware/ip-whitelist.middleware.ts +++ b/src/middleware/ip-whitelist.middleware.ts @@ -17,4 +17,4 @@ export function ipWhitelistMiddleware(allowedCidrs: string[]) { next(); }; -} \ No newline at end of file +} diff --git a/src/middleware/rate-limit-wallet.middleware.ts b/src/middleware/rate-limit-wallet.middleware.ts index a9f2765..59443db 100644 --- a/src/middleware/rate-limit-wallet.middleware.ts +++ b/src/middleware/rate-limit-wallet.middleware.ts @@ -3,83 +3,83 @@ import type { AuthenticatedRequest } from "../types/auth"; import { HttpError } from "../utils/http-error"; interface WalletRateLimitEntry { - count: number; - windowStart: number; + count: number; + windowStart: number; } interface WalletRateLimitConfig { - windowMs: number; - maxRequests: number; + windowMs: number; + maxRequests: number; } const stores = new Map>(); function getStore(name: string): Map { - let store = stores.get(name); - if (!store) { - store = new Map(); - stores.set(name, store); - } - return store; + let store = stores.get(name); + if (!store) { + store = new Map(); + stores.set(name, store); + } + return store; } function getWalletAddress(req: Request): string | null { - const authReq = req as AuthenticatedRequest; - return authReq.user?.stellarAddress ?? null; + const authReq = req as AuthenticatedRequest; + return authReq.user?.stellarAddress ?? null; } export function createWalletRateLimiter(config: WalletRateLimitConfig, name: string) { - const store = getStore(name); + const store = getStore(name); - // Periodically clean up stale entries - setInterval(() => { - const now = Date.now(); - for (const [key, entry] of store) { - if (now - entry.windowStart >= config.windowMs) { - store.delete(key); - } - } - }, config.windowMs).unref(); + // Periodically clean up stale entries + setInterval(() => { + const now = Date.now(); + for (const [key, entry] of store) { + if (now - entry.windowStart >= config.windowMs) { + store.delete(key); + } + } + }, config.windowMs).unref(); - return (req: Request, res: Response, next: NextFunction): void => { - const wallet = getWalletAddress(req); + return (req: Request, res: Response, next: NextFunction): void => { + const wallet = getWalletAddress(req); - if (!wallet) { - next(new HttpError(401, "Authentication required for rate-limited endpoint.")); - return; - } + if (!wallet) { + next(new HttpError(401, "Authentication required for rate-limited endpoint.")); + return; + } - const now = Date.now(); - const entry = store.get(wallet); + const now = Date.now(); + const entry = store.get(wallet); - if (!entry || now - entry.windowStart >= config.windowMs) { - // Start a new window - store.set(wallet, { count: 1, windowStart: now }); - next(); - return; - } + if (!entry || now - entry.windowStart >= config.windowMs) { + // Start a new window + store.set(wallet, { count: 1, windowStart: now }); + next(); + return; + } - if (entry.count >= config.maxRequests) { - const retryAfterMs = config.windowMs - (now - entry.windowStart); - const retryAfterSeconds = Math.ceil(retryAfterMs / 1000); + if (entry.count >= config.maxRequests) { + const retryAfterMs = config.windowMs - (now - entry.windowStart); + const retryAfterSeconds = Math.ceil(retryAfterMs / 1000); - res.setHeader("Retry-After", String(retryAfterSeconds)); - res.status(429).json({ - success: false, - error: { - code: "RATE_LIMIT_EXCEEDED", - message: `Too many requests. Please wait ${retryAfterSeconds} seconds before retrying.`, - }, - }); - return; - } + res.setHeader("Retry-After", String(retryAfterSeconds)); + res.status(429).json({ + success: false, + error: { + code: "RATE_LIMIT_EXCEEDED", + message: `Too many requests. Please wait ${retryAfterSeconds} seconds before retrying.`, + }, + }); + return; + } - entry.count++; - next(); - }; + entry.count++; + next(); + }; } // For testing: allow resetting stores export function resetRateLimitStores(): void { - stores.clear(); -} \ No newline at end of file + stores.clear(); +} diff --git a/src/middleware/rate-limit.middleware.ts b/src/middleware/rate-limit.middleware.ts index eac3ced..78a93d2 100644 --- a/src/middleware/rate-limit.middleware.ts +++ b/src/middleware/rate-limit.middleware.ts @@ -1,4 +1,5 @@ import rateLimit from "express-rate-limit"; +import type { Request as ExpressRequest } from "express"; import type { AppLogger } from "../observability/logger"; import { HttpError } from "../utils/http-error"; @@ -7,6 +8,7 @@ export interface RateLimitOptions { max: number; message?: string; code?: string; + keyGenerator?: (req: ExpressRequest) => string; } const DEFAULT_GLOBAL_LIMIT: RateLimitOptions = { @@ -16,20 +18,28 @@ const DEFAULT_GLOBAL_LIMIT: RateLimitOptions = { code: "RATE_LIMIT_EXCEEDED", }; -const DEFAULT_AUTH_LIMIT: RateLimitOptions = { - windowMs: 15 * 60 * 1000, - max: 10, - message: "Too many authentication attempts, please try again later.", - code: "AUTH_RATE_LIMIT_EXCEEDED", +const DEFAULT_CHALLENGE_LIMIT: RateLimitOptions = { + windowMs: 60 * 1000, + max: 5, + message: "Too many challenge requests, please try again later.", + code: "CHALLENGE_RATE_LIMIT_EXCEEDED", +}; + +const DEFAULT_VERIFY_LIMIT: RateLimitOptions = { + windowMs: 60 * 1000, + max: 20, + message: "Too many verification attempts, please try again later.", + code: "VERIFY_RATE_LIMIT_EXCEEDED", }; export function createRateLimitMiddleware( logger: AppLogger, - options: RateLimitOptions = DEFAULT_GLOBAL_LIMIT, + options: RateLimitOptions = DEFAULT_GLOBAL_LIMIT ) { const limiter = rateLimit({ windowMs: options.windowMs, max: options.max, + keyGenerator: options.keyGenerator, message: { success: false, error: { @@ -50,7 +60,7 @@ export function createRateLimitMiddleware( const error = new HttpError( 429, - nextOptions?.message ?? "Too many requests, please try again later.", + nextOptions?.message ?? "Too many requests, please try again later." ); next(error); @@ -60,8 +70,16 @@ export function createRateLimitMiddleware( return limiter; } +export function createChallengeRateLimitMiddleware(logger: AppLogger) { + return createRateLimitMiddleware(logger, DEFAULT_CHALLENGE_LIMIT); +} + +export function createVerifyRateLimitMiddleware(logger: AppLogger) { + return createRateLimitMiddleware(logger, DEFAULT_VERIFY_LIMIT); +} + export function createAuthRateLimitMiddleware(logger: AppLogger) { - return createRateLimitMiddleware(logger, DEFAULT_AUTH_LIMIT); + return createRateLimitMiddleware(logger, DEFAULT_VERIFY_LIMIT); } export function applyRateLimiters( @@ -70,7 +88,7 @@ export function applyRateLimiters( config?: { global?: Partial; auth?: Partial; - }, + } ) { const globalOptions: RateLimitOptions = { ...DEFAULT_GLOBAL_LIMIT, diff --git a/src/middleware/request-observability.middleware.ts b/src/middleware/request-observability.middleware.ts index cb8ab86..004b645 100644 --- a/src/middleware/request-observability.middleware.ts +++ b/src/middleware/request-observability.middleware.ts @@ -49,7 +49,7 @@ function resolveRequestId(requestIdHeader: string | string[] | undefined): strin } export function createRequestObservabilityMiddleware( - dependencies: RequestObservabilityDependencies, + dependencies: RequestObservabilityDependencies ) { return (req: Request, res: Response, next: NextFunction): void => { const requestId = resolveRequestId(req.header("x-request-id")); diff --git a/src/middleware/sanitize-input.middleware.ts b/src/middleware/sanitize-input.middleware.ts index 9e364e1..4593712 100644 --- a/src/middleware/sanitize-input.middleware.ts +++ b/src/middleware/sanitize-input.middleware.ts @@ -42,11 +42,7 @@ function sanitizeObject(obj: Record): Record { return sanitized; } -export function sanitizeInputMiddleware( - req: Request, - _res: Response, - next: NextFunction, -): void { +export function sanitizeInputMiddleware(req: Request, _res: Response, next: NextFunction): void { if (req.body && typeof req.body === "object" && !isBuffer(req.body)) { req.body = sanitizeObject(req.body); } diff --git a/src/middleware/validate.middleware.ts b/src/middleware/validate.middleware.ts index 0d204bd..461b42f 100644 --- a/src/middleware/validate.middleware.ts +++ b/src/middleware/validate.middleware.ts @@ -14,8 +14,8 @@ export function validateBody(schema: ObjectSchema) { new HttpError( 400, "Request validation failed.", - error.details.map((detail) => detail.message), - ), + error.details.map((detail) => detail.message) + ) ); return; } diff --git a/src/migrations/1712000000000-CreateWebhookSubscriptionsTable.ts b/src/migrations/1712000000000-CreateWebhookSubscriptionsTable.ts index a4e7474..e19cbcc 100644 --- a/src/migrations/1712000000000-CreateWebhookSubscriptionsTable.ts +++ b/src/migrations/1712000000000-CreateWebhookSubscriptionsTable.ts @@ -1,8 +1,6 @@ import { MigrationInterface, QueryRunner } from "typeorm"; -export class CreateWebhookSubscriptionsTable1712000000000 - implements MigrationInterface -{ +export class CreateWebhookSubscriptionsTable1712000000000 implements MigrationInterface { name = "CreateWebhookSubscriptionsTable1712000000000"; public async up(queryRunner: QueryRunner): Promise { diff --git a/src/migrations/1713000000000-CreateSorobanEventLogsTable.ts b/src/migrations/1713000000000-CreateSorobanEventLogsTable.ts index 988a2e6..47f1c92 100644 --- a/src/migrations/1713000000000-CreateSorobanEventLogsTable.ts +++ b/src/migrations/1713000000000-CreateSorobanEventLogsTable.ts @@ -1,8 +1,6 @@ import { MigrationInterface, QueryRunner } from "typeorm"; -export class CreateSorobanEventLogsTable1713000000000 - implements MigrationInterface -{ +export class CreateSorobanEventLogsTable1713000000000 implements MigrationInterface { name = "CreateSorobanEventLogsTable1713000000000"; public async up(queryRunner: QueryRunner): Promise { diff --git a/src/migrations/1714000000000-AddSorobanEventLogsIndex.ts b/src/migrations/1714000000000-AddSorobanEventLogsIndex.ts index 077f91e..c235db5 100644 --- a/src/migrations/1714000000000-AddSorobanEventLogsIndex.ts +++ b/src/migrations/1714000000000-AddSorobanEventLogsIndex.ts @@ -1,8 +1,6 @@ import { MigrationInterface, QueryRunner } from "typeorm"; -export class AddSorobanEventLogsIndex1714000000000 - implements MigrationInterface -{ +export class AddSorobanEventLogsIndex1714000000000 implements MigrationInterface { name = "AddSorobanEventLogsIndex1714000000000"; public async up(queryRunner: QueryRunner): Promise { diff --git a/src/migrations/1731700000000-AddInvestmentPaymentVerification.ts b/src/migrations/1731700000000-AddInvestmentPaymentVerification.ts index a5dab1f..67ab896 100644 --- a/src/migrations/1731700000000-AddInvestmentPaymentVerification.ts +++ b/src/migrations/1731700000000-AddInvestmentPaymentVerification.ts @@ -1,8 +1,6 @@ import { MigrationInterface, QueryRunner } from "typeorm"; -export class AddInvestmentPaymentVerification1731700000000 - implements MigrationInterface -{ +export class AddInvestmentPaymentVerification1731700000000 implements MigrationInterface { name = "AddInvestmentPaymentVerification1731700000000"; public async up(queryRunner: QueryRunner): Promise { diff --git a/src/migrations/1731800000000-AddTransactionInvoiceAndInvestmentLinks.ts b/src/migrations/1731800000000-AddTransactionInvoiceAndInvestmentLinks.ts index 2435b97..b874875 100644 --- a/src/migrations/1731800000000-AddTransactionInvoiceAndInvestmentLinks.ts +++ b/src/migrations/1731800000000-AddTransactionInvoiceAndInvestmentLinks.ts @@ -1,8 +1,6 @@ import { MigrationInterface, QueryRunner } from "typeorm"; -export class AddTransactionInvoiceAndInvestmentLinks1731800000000 - implements MigrationInterface -{ +export class AddTransactionInvoiceAndInvestmentLinks1731800000000 implements MigrationInterface { name = "AddTransactionInvoiceAndInvestmentLinks1731800000000"; public async up(queryRunner: QueryRunner): Promise { diff --git a/src/migrations/1731900000001-AddUserKycVerifiedFlag.ts b/src/migrations/1731900000001-AddUserKycVerifiedFlag.ts index 5206fca..44cae7c 100644 --- a/src/migrations/1731900000001-AddUserKycVerifiedFlag.ts +++ b/src/migrations/1731900000001-AddUserKycVerifiedFlag.ts @@ -10,7 +10,7 @@ export class AddUserKycVerifiedFlag1731900000001 implements MigrationInterface { name: "is_kyc_verified", type: "boolean", default: false, - }), + }) ); await queryRunner.query(` UPDATE "users" diff --git a/src/migrations/1732100000000-CreateWebhookDeliveryLogsTable.ts b/src/migrations/1732100000000-CreateWebhookDeliveryLogsTable.ts index 0804b31..5009797 100644 --- a/src/migrations/1732100000000-CreateWebhookDeliveryLogsTable.ts +++ b/src/migrations/1732100000000-CreateWebhookDeliveryLogsTable.ts @@ -3,8 +3,12 @@ import { MigrationInterface, QueryRunner } from "typeorm"; export class CreateWebhookDeliveryLogsTable1732100000000 implements MigrationInterface { name = "CreateWebhookDeliveryLogsTable1732100000000"; public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query(`CREATE TABLE "webhook_delivery_logs" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "subscription_id" uuid NOT NULL, "event_type" character varying(100) NOT NULL, "attempt" integer NOT NULL, "response_status" integer, "delivered" boolean NOT NULL, "error_message" text, "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), CONSTRAINT "PK_webhook_delivery_logs" PRIMARY KEY ("id"), CONSTRAINT "FK_webhook_delivery_logs_subscription" FOREIGN KEY ("subscription_id") REFERENCES "webhook_subscriptions"("id") ON DELETE CASCADE);`); - await queryRunner.query(`CREATE INDEX "idx_webhook_delivery_logs_subscription_id" ON "webhook_delivery_logs" ("subscription_id")`); + await queryRunner.query( + `CREATE TABLE "webhook_delivery_logs" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "subscription_id" uuid NOT NULL, "event_type" character varying(100) NOT NULL, "attempt" integer NOT NULL, "response_status" integer, "delivered" boolean NOT NULL, "error_message" text, "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), CONSTRAINT "PK_webhook_delivery_logs" PRIMARY KEY ("id"), CONSTRAINT "FK_webhook_delivery_logs_subscription" FOREIGN KEY ("subscription_id") REFERENCES "webhook_subscriptions"("id") ON DELETE CASCADE);` + ); + await queryRunner.query( + `CREATE INDEX "idx_webhook_delivery_logs_subscription_id" ON "webhook_delivery_logs" ("subscription_id")` + ); } public async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`DROP INDEX "public"."idx_webhook_delivery_logs_subscription_id"`); diff --git a/src/migrations/1732200000000-AddWebhookDeliveryEventId.ts b/src/migrations/1732200000000-AddWebhookDeliveryEventId.ts index cf83558..082bd52 100644 --- a/src/migrations/1732200000000-AddWebhookDeliveryEventId.ts +++ b/src/migrations/1732200000000-AddWebhookDeliveryEventId.ts @@ -5,19 +5,15 @@ export class AddWebhookDeliveryEventId1732200000000 implements MigrationInterfac public async up(queryRunner: QueryRunner): Promise { await queryRunner.query( - `ALTER TABLE "webhook_delivery_logs" ADD "event_id" character varying(200)`, + `ALTER TABLE "webhook_delivery_logs" ADD "event_id" character varying(200)` ); await queryRunner.query( - `CREATE INDEX "idx_webhook_delivery_logs_event_id" ON "webhook_delivery_logs" ("event_id")`, + `CREATE INDEX "idx_webhook_delivery_logs_event_id" ON "webhook_delivery_logs" ("event_id")` ); } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `DROP INDEX "public"."idx_webhook_delivery_logs_event_id"`, - ); - await queryRunner.query( - `ALTER TABLE "webhook_delivery_logs" DROP COLUMN "event_id"`, - ); + await queryRunner.query(`DROP INDEX "public"."idx_webhook_delivery_logs_event_id"`); + await queryRunner.query(`ALTER TABLE "webhook_delivery_logs" DROP COLUMN "event_id"`); } } diff --git a/src/models/AuthChallenge.model.ts b/src/models/AuthChallenge.model.ts index 047e75f..98cf2ee 100644 --- a/src/models/AuthChallenge.model.ts +++ b/src/models/AuthChallenge.model.ts @@ -1,10 +1,4 @@ -import { - Column, - CreateDateColumn, - Entity, - Index, - PrimaryGeneratedColumn, -} from "typeorm"; +import { Column, CreateDateColumn, Entity, Index, PrimaryGeneratedColumn } from "typeorm"; @Entity("auth_challenges") @Index("idx_auth_challenges_address_nonce", ["stellarAddress", "nonceHash"], { diff --git a/src/models/KYCVerification.model.ts b/src/models/KYCVerification.model.ts index 57788c4..4a53796 100644 --- a/src/models/KYCVerification.model.ts +++ b/src/models/KYCVerification.model.ts @@ -1,11 +1,4 @@ -import { - Entity, - PrimaryGeneratedColumn, - Column, - ManyToOne, - JoinColumn, - Index, -} from "typeorm"; +import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn, Index } from "typeorm"; import { KYCStatus, KYCVerificationType } from "../types/enums"; @Entity("kyc_verifications") diff --git a/src/models/Notification.model.ts b/src/models/Notification.model.ts index ed57a50..af2833a 100644 --- a/src/models/Notification.model.ts +++ b/src/models/Notification.model.ts @@ -1,11 +1,4 @@ -import { - Entity, - PrimaryGeneratedColumn, - Column, - ManyToOne, - JoinColumn, - Index, -} from "typeorm"; +import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn, Index } from "typeorm"; import { NotificationType } from "../types/enums"; @Entity("notifications") diff --git a/src/models/SorobanEventLog.model.ts b/src/models/SorobanEventLog.model.ts index d0de18c..10c4450 100644 --- a/src/models/SorobanEventLog.model.ts +++ b/src/models/SorobanEventLog.model.ts @@ -1,10 +1,4 @@ -import { - Column, - CreateDateColumn, - Entity, - Index, - PrimaryGeneratedColumn, -} from "typeorm"; +import { Column, CreateDateColumn, Entity, Index, PrimaryGeneratedColumn } from "typeorm"; @Entity("soroban_event_logs") export class SorobanEventLog { diff --git a/src/models/Transaction.model.ts b/src/models/Transaction.model.ts index 1b89539..8a93bd9 100644 --- a/src/models/Transaction.model.ts +++ b/src/models/Transaction.model.ts @@ -1,17 +1,9 @@ -import { - Entity, - PrimaryGeneratedColumn, - Column, - ManyToOne, - JoinColumn, - Index, -} from "typeorm"; +import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn, Index } from "typeorm"; import { TransactionType, TransactionStatus } from "../types/enums"; import type { Investment } from "./Investment.model"; import type { Invoice } from "./Invoice.model"; - @Entity("transactions") export class Transaction { @PrimaryGeneratedColumn("uuid") @@ -25,12 +17,10 @@ export class Transaction { @Index("idx_transactions_investment_id") investmentId!: string | null; - @Column({ name: "invoice_id", type: "uuid", nullable: true }) @Index("idx_transactions_invoice_id") invoiceId!: string | null; - @Column({ type: "enum", enum: TransactionType, @@ -66,9 +56,7 @@ export class Transaction { @JoinColumn({ name: "investment_id" }) investment!: Investment | null; - @ManyToOne("Invoice", "transactions", { onDelete: "SET NULL", nullable: true }) @JoinColumn({ name: "invoice_id" }) invoice!: Invoice | null; - } diff --git a/src/models/WebhookDeliveryLog.model.ts b/src/models/WebhookDeliveryLog.model.ts index 891a2ee..299603a 100644 --- a/src/models/WebhookDeliveryLog.model.ts +++ b/src/models/WebhookDeliveryLog.model.ts @@ -3,11 +3,17 @@ import { Column, CreateDateColumn, Entity, Index, PrimaryGeneratedColumn } from @Entity("webhook_delivery_logs") export class WebhookDeliveryLog { @PrimaryGeneratedColumn("uuid") id!: string; - @Column({ name: "subscription_id", type: "uuid" }) @Index("idx_webhook_delivery_logs_subscription_id") subscriptionId!: string; + @Column({ name: "subscription_id", type: "uuid" }) + @Index("idx_webhook_delivery_logs_subscription_id") + subscriptionId!: string; @Column({ name: "event_type", type: "varchar", length: 100 }) eventType!: string; - @Column({ name: "event_id", type: "varchar", length: 200, nullable: true }) @Index("idx_webhook_delivery_logs_event_id") eventId!: string | null; + @Column({ name: "event_id", type: "varchar", length: 200, nullable: true }) + @Index("idx_webhook_delivery_logs_event_id") + eventId!: string | null; @Column({ name: "attempt", type: "integer" }) attempt!: number; - @Column({ name: "response_status", type: "integer", nullable: true }) responseStatus!: number | null; + @Column({ name: "response_status", type: "integer", nullable: true }) responseStatus!: + | number + | null; @Column({ name: "delivered", type: "boolean" }) delivered!: boolean; @Column({ name: "error_message", type: "text", nullable: true }) errorMessage!: string | null; @CreateDateColumn({ name: "created_at", type: "timestamptz" }) createdAt!: Date; diff --git a/src/observability/logger.ts b/src/observability/logger.ts index f7e71f8..305bb6c 100644 --- a/src/observability/logger.ts +++ b/src/observability/logger.ts @@ -37,9 +37,7 @@ class WinstonAppLogger implements AppLogger { function createBaseLogger(): winston.Logger { return winston.createLogger({ - level: - process.env.LOG_LEVEL ?? - (process.env.NODE_ENV === "test" ? "silent" : "info"), + level: process.env.LOG_LEVEL ?? (process.env.NODE_ENV === "test" ? "silent" : "info"), defaultMeta: { service: "stellarsettle-api", }, @@ -47,7 +45,7 @@ function createBaseLogger(): winston.Logger { redactionFormat(), winston.format.timestamp(), winston.format.errors({ stack: true }), - winston.format.json(), + winston.format.json() ), transports: [new winston.transports.Console()], }); diff --git a/src/observability/metrics.ts b/src/observability/metrics.ts index 8bdf209..b7c863d 100644 --- a/src/observability/metrics.ts +++ b/src/observability/metrics.ts @@ -25,7 +25,7 @@ function escapeLabelValue(value: string): string { function buildLabelSet(labels: RequestMetricLabels): string { return `method="${escapeLabelValue(labels.method)}",route="${escapeLabelValue( - labels.route, + labels.route )}",status_class="${escapeLabelValue(labels.statusClass)}"`; } @@ -36,6 +36,7 @@ function buildMetricKey(labels: RequestMetricLabels): string { export class MetricsRegistry { private readonly requestCounters = new Map(); private readonly requestDurationHistograms = new Map(); + private readonly customCounters = new Map(); recordHttpRequest(input: RequestMetricLabels & { durationMs: number }): void { const labels: RequestMetricLabels = { @@ -80,13 +81,13 @@ export class MetricsRegistry { for (const metric of this.requestCounters.values()) { lines.push( - `stellarsettle_http_requests_total{${buildLabelSet(metric.labels)}} ${metric.value}`, + `stellarsettle_http_requests_total{${buildLabelSet(metric.labels)}} ${metric.value}` ); } lines.push( "# HELP stellarsettle_http_request_duration_ms HTTP request duration in milliseconds.", - "# TYPE stellarsettle_http_request_duration_ms histogram", + "# TYPE stellarsettle_http_request_duration_ms histogram" ); for (const metric of this.requestDurationHistograms.values()) { @@ -96,28 +97,46 @@ export class MetricsRegistry { cumulativeCount += metric.bucketCounts[index]; lines.push( `stellarsettle_http_request_duration_ms_bucket{${buildLabelSet( - metric.labels, - )},le="${HTTP_DURATION_BUCKETS_MS[index]}"} ${cumulativeCount}`, + metric.labels + )},le="${HTTP_DURATION_BUCKETS_MS[index]}"} ${cumulativeCount}` ); } lines.push( `stellarsettle_http_request_duration_ms_bucket{${buildLabelSet( - metric.labels, + metric.labels )},le="+Inf"} ${metric.count}`, `stellarsettle_http_request_duration_ms_sum{${buildLabelSet(metric.labels)}} ${metric.sum}`, - `stellarsettle_http_request_duration_ms_count{${buildLabelSet(metric.labels)}} ${metric.count}`, + `stellarsettle_http_request_duration_ms_count{${buildLabelSet(metric.labels)}} ${metric.count}` + ); + } + + for (const [key, value] of this.customCounters.entries()) { + lines.push( + `# HELP ${key}_total Custom counter.`, + `# TYPE ${key}_total counter`, + `${key}_total ${value}` ); } lines.push( "# HELP stellarsettle_process_uptime_seconds Process uptime in seconds.", "# TYPE stellarsettle_process_uptime_seconds gauge", - `stellarsettle_process_uptime_seconds ${process.uptime()}`, + `stellarsettle_process_uptime_seconds ${process.uptime()}` ); return `${lines.join("\n")}\n`; } + + increment(name: string, labels?: Record): void { + const key = labels + ? `${name}{${Object.entries(labels) + .map(([k, v]) => `${k}="${v}"`) + .join(",")}}` + : name; + const current = this.customCounters.get(key) ?? 0; + this.customCounters.set(key, current + 1); + } } export function getMetricsContentType(): string { diff --git a/src/observability/redaction-formatter.ts b/src/observability/redaction-formatter.ts index 101994b..f0256b8 100644 --- a/src/observability/redaction-formatter.ts +++ b/src/observability/redaction-formatter.ts @@ -2,11 +2,9 @@ import winston from "winston"; const STELLAR_SECRET_KEY_PATTERN = /S[A-Z0-9]{55}/g; -const STELLAR_SECRET_KEY_REDACTED = - "S*******************************************************"; +const STELLAR_SECRET_KEY_REDACTED = "S*******************************************************"; -const JWT_PATTERN = - /eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]+/g; +const JWT_PATTERN = /eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]+/g; const BEARER_PATTERN = /Bearer\s+[A-Za-z0-9_\-.~+/]+=*/g; diff --git a/src/routes/admin/admin.routes.ts b/src/routes/admin/admin.routes.ts index 6902cdf..59ca7df 100644 --- a/src/routes/admin/admin.routes.ts +++ b/src/routes/admin/admin.routes.ts @@ -43,4 +43,4 @@ export function createAdminRouter({ }); return router; -} \ No newline at end of file +} diff --git a/src/routes/admin/approve-kyc.ts b/src/routes/admin/approve-kyc.ts index 2b9f3af..45c706f 100644 --- a/src/routes/admin/approve-kyc.ts +++ b/src/routes/admin/approve-kyc.ts @@ -10,7 +10,11 @@ interface ApproveKYCBody { reviewerId: string; } -export async function approveKYC(req: Request, res: Response, dataSource: DataSource) { +export async function approveKYC( + req: Request, + res: Response, + dataSource: DataSource +) { try { const adminKey = req.headers["x-admin-key"]; if (adminKey !== process.env.ADMIN_API_KEY) { diff --git a/src/routes/admin/reject-invoice.ts b/src/routes/admin/reject-invoice.ts index 4e6aec7..42fce08 100644 --- a/src/routes/admin/reject-invoice.ts +++ b/src/routes/admin/reject-invoice.ts @@ -26,7 +26,7 @@ interface RejectInvoiceParams { export async function rejectInvoice( req: Request, res: Response, - invoiceService: InvoiceService, + invoiceService: InvoiceService ) { try { const adminKey = req.headers["x-admin-key"]; diff --git a/src/routes/admin/reject-kyc.ts b/src/routes/admin/reject-kyc.ts index 75ac4a1..2071a1d 100644 --- a/src/routes/admin/reject-kyc.ts +++ b/src/routes/admin/reject-kyc.ts @@ -11,7 +11,11 @@ interface RejectKYCBody { rejectionReason: string; } -export async function rejectKYC(req: Request, res: Response, dataSource: DataSource) { +export async function rejectKYC( + req: Request, + res: Response, + dataSource: DataSource +) { try { const adminKey = req.headers["x-admin-key"]; if (adminKey !== process.env.ADMIN_API_KEY) { diff --git a/src/routes/admin/revoke-kyc.ts b/src/routes/admin/revoke-kyc.ts index 84716ad..f0600c2 100644 --- a/src/routes/admin/revoke-kyc.ts +++ b/src/routes/admin/revoke-kyc.ts @@ -20,7 +20,11 @@ interface RevokeKYCBody { * them able to re-submit. Only an approved user can be revoked — revoking * anything else would be a no-op that still wrote an audit entry. */ -export async function revokeKYC(req: Request, res: Response, dataSource: DataSource) { +export async function revokeKYC( + req: Request, + res: Response, + dataSource: DataSource +) { try { const adminKey = req.headers["x-admin-key"]; if (adminKey !== process.env.ADMIN_API_KEY) { diff --git a/src/routes/auth.routes.ts b/src/routes/auth.routes.ts index b949ebf..a04fc21 100644 --- a/src/routes/auth.routes.ts +++ b/src/routes/auth.routes.ts @@ -1,16 +1,28 @@ -import { Router, type NextFunction, type Request, type RequestHandler, type Response } from "express"; +import { + Router, + type NextFunction, + type Request, + type RequestHandler, + type Response, + type ErrorRequestHandler, +} from "express"; import Joi from "joi"; import { createAuthController } from "../controllers/auth.controller"; import { createAuthMiddleware } from "../middleware/auth.middleware"; import { validateBody } from "../middleware/validate.middleware"; -import { createAuthRateLimitMiddleware } from "../middleware/rate-limit.middleware"; +import { + createChallengeRateLimitMiddleware, + createVerifyRateLimitMiddleware, +} from "../middleware/rate-limit.middleware"; +import { createCircuitBreaker } from "../lib/circuit-breaker"; import type { AuthService } from "../services/auth.service"; import type { AppLogger } from "../observability/logger"; +import { HttpError } from "../utils/http-error"; // Strict schemas: enforce Stellar G... format hint, length bounds, and sanitized inputs. const STELLAR_PUBLIC_KEY_PATTERN = /^G[A-Z2-7]{55}$/; const NONCE_PATTERN = /^[A-Za-z0-9:_-]+$/; -const SIGNATURE_PATTERN = /^[A-Za-z0-9+/=_:\-\.]+$/; +const SIGNATURE_PATTERN = /^[A-Za-z0-9+/=:_\-.]+$/; type AsyncRouteHandler = (req: Request, res: Response, next: NextFunction) => Promise | void; @@ -57,7 +69,7 @@ const verifySchema = Joi.object({ function wrapAuthHandler( routeName: string, handler: AsyncRouteHandler, - logger: AppLogger, + logger: AppLogger ): RequestHandler { return async (req, res, next) => { try { @@ -85,40 +97,148 @@ function markAuthRouteBase(): RequestHandler { function noStoreAuthResponse(): RequestHandler { return (_req, res, next) => { res.setHeader("Cache-Control", "no-store"); + res.setHeader("X-Content-Type-Options", "nosniff"); + res.setHeader("X-Frame-Options", "DENY"); next(); }; } +function extractIdempotencyKey(req: Request): string | null { + const key = req.headers["idempotency-key"] as string | undefined; + return key || null; +} + +function createIdempotencyMiddleware() { + const cache = new Map< + string, + { status: number; body: Record; expiresAt: number } + >(); + const TTL_MS = 60 * 60 * 1000; + + setInterval( + () => { + const now = Date.now(); + for (const [key, value] of cache.entries()) { + if (value.expiresAt < now) { + cache.delete(key); + } + } + }, + 5 * 60 * 1000 + ); + + return (req: Request, res: Response, next: NextFunction) => { + const key = extractIdempotencyKey(req); + if (!key) { + return next(); + } + + const cached = cache.get(key); + if (cached) { + res.setHeader("X-Idempotency-Replay", "true"); + return res.status(cached.status).json(cached.body); + } + + const originalJson = res.json.bind(res); + res.json = (body: Record) => { + if (res.statusCode < 400) { + cache.set(key, { status: res.statusCode, body, expiresAt: Date.now() + TTL_MS }); + } + return originalJson(body); + }; + + next(); + }; +} + +function normalizeErrorResponse(): ErrorRequestHandler { + return (err: Error, req: Request, res: Response, _next: NextFunction): void => { + if (err instanceof HttpError) { + res.status(err.statusCode).json({ + success: false, + error: { + code: err.code ?? "INTERNAL_ERROR", + message: err.message, + details: err.details, + }, + requestId: req.headers["x-request-id"], + }); + return; + } + + res.status(500).json({ + success: false, + error: { + code: "INTERNAL_ERROR", + message: "An unexpected error occurred", + }, + requestId: req.headers["x-request-id"], + }); + }; +} + export function createAuthRouter(authService: AuthService, logger: AppLogger): Router { const router = Router(); const controller = createAuthController(authService); const authMiddleware = createAuthMiddleware(authService); - // `/challenge` and `/verify` are unauthenticated by design: the wallet - // signature is the auth check, so they need their own abuse protection. - const authRateLimiter = createAuthRateLimitMiddleware(logger); + + const challengeRateLimiter = createChallengeRateLimitMiddleware(logger); + const verifyRateLimiter = createVerifyRateLimitMiddleware(logger); + const idempotencyMiddleware = createIdempotencyMiddleware(); + const circuitBreaker = createCircuitBreaker({ failureThreshold: 5, timeout: 30000 }); + + const withCircuitBreaker = (handler: RequestHandler): RequestHandler => { + return async (req, res, next) => { + try { + await circuitBreaker.execute(async () => { + await new Promise((resolve, reject) => { + handler(req, res, (err) => (err ? reject(err) : resolve())); + }); + }); + } catch (error) { + if (error instanceof Error && error.message === "Circuit breaker is open") { + logger.warn("Circuit breaker open for auth route", { route: req.path }); + return next( + new HttpError(503, "Service temporarily unavailable", "CIRCUIT_BREAKER_OPEN") + ); + } + next(error); + } + }; + }; + + const withCircuitBreakerAndWrap = ( + routeName: string, + handler: AsyncRouteHandler + ): RequestHandler => { + return withCircuitBreaker(wrapAuthHandler(routeName, handler, logger)); + }; router.use(markAuthRouteBase()); router.use(noStoreAuthResponse()); + router.use(idempotencyMiddleware); router.post( "/challenge", - authRateLimiter, + challengeRateLimiter, validateBody(challengeSchema), - wrapAuthHandler("auth.challenge", controller.challenge as AsyncRouteHandler, logger), + withCircuitBreakerAndWrap("auth.challenge", controller.challenge as AsyncRouteHandler) ); router.post( "/verify", - authRateLimiter, + verifyRateLimiter, validateBody(verifySchema), - wrapAuthHandler("auth.verify", controller.verify as AsyncRouteHandler, logger), + withCircuitBreakerAndWrap("auth.verify", controller.verify as AsyncRouteHandler) ); router.get( "/me", authMiddleware, - wrapAuthHandler("auth.me", controller.me as AsyncRouteHandler, logger), + wrapAuthHandler("auth.me", controller.me as AsyncRouteHandler, logger) ); + router.use(normalizeErrorResponse()); + return router; -} \ No newline at end of file +} diff --git a/src/routes/investment.routes.ts b/src/routes/investment.routes.ts index ed27df4..53985ef 100644 --- a/src/routes/investment.routes.ts +++ b/src/routes/investment.routes.ts @@ -17,7 +17,7 @@ export interface InvestmentRouterDependencies { // Per-wallet rate limit: max 10 investment submissions per 60 seconds const investmentRateLimiter = createWalletRateLimiter( { windowMs: 60_000, maxRequests: 10 }, - "investment-create", + "investment-create" ); export function createInvestmentRouter({ @@ -37,7 +37,13 @@ export function createInvestmentRouter({ : []; // POST /api/v1/investments - Create a new investment commitment - router.post("/", authMiddleware, ...pauseGuard, investmentRateLimiter, controller.createInvestment); + router.post( + "/", + authMiddleware, + ...pauseGuard, + investmentRateLimiter, + controller.createInvestment + ); // GET /api/v1/investments/dashboard - Investor portfolio aggregate router.get("/dashboard", authMiddleware, controller.getDashboard); diff --git a/src/routes/investments/create.ts b/src/routes/investments/create.ts index 9b63feb..3ce5b9d 100644 --- a/src/routes/investments/create.ts +++ b/src/routes/investments/create.ts @@ -21,4 +21,4 @@ export async function createInvestment(req: AuthenticatedRequest, res: Response) }, }); } -} \ No newline at end of file +} diff --git a/src/routes/invoice.routes.ts b/src/routes/invoice.routes.ts index d387032..8e68815 100644 --- a/src/routes/invoice.routes.ts +++ b/src/routes/invoice.routes.ts @@ -23,7 +23,9 @@ const createInvoiceSchema = Joi.object({ amount: Joi.string() .required() .pattern(/^\d+(\.\d{1,4})?$/) - .messages({ "string.pattern.base": "amount must be a decimal number with max 4 decimal places" }), + .messages({ + "string.pattern.base": "amount must be a decimal number with max 4 decimal places", + }), discountRate: Joi.string() .required() .pattern(/^\d+(\.\d{1,2})?$/) @@ -34,7 +36,9 @@ const createInvoiceSchema = Joi.object({ } return value; }) - .messages({ "any.invalid": "discountRate must be a percentage (0-100) with max 2 decimal places" }), + .messages({ + "any.invalid": "discountRate must be a percentage (0-100) with max 2 decimal places", + }), dueDate: Joi.date().iso().required(), ipfsHash: Joi.string().optional().trim().max(128), riskScore: Joi.string() @@ -47,7 +51,9 @@ const createInvoiceSchema = Joi.object({ } return value; }) - .messages({ "any.invalid": "riskScore must be a percentage (0-100) with max 2 decimal places" }), + .messages({ + "any.invalid": "riskScore must be a percentage (0-100) with max 2 decimal places", + }), }); const updateInvoiceSchema = Joi.object({ @@ -55,12 +61,16 @@ const updateInvoiceSchema = Joi.object({ amount: Joi.string() .optional() .pattern(/^\d+(\.\d{1,4})?$/) - .messages({ "string.pattern.base": "amount must be a decimal number with max 4 decimal places" }), + .messages({ + "string.pattern.base": "amount must be a decimal number with max 4 decimal places", + }), discountRate: Joi.string() .optional() .pattern(/^\d+(\.\d{1,2})?$/) .max(100) - .messages({ "string.pattern.base": "discountRate must be a percentage (0-100) with max 2 decimal places" }), + .messages({ + "string.pattern.base": "discountRate must be a percentage (0-100) with max 2 decimal places", + }), dueDate: Joi.date().iso().optional(), riskScore: Joi.string() .optional() @@ -89,12 +99,12 @@ const getInvoicesQuerySchema = Joi.object({ const calculateTermsSchema = Joi.object({ faceValue: Joi.alternatives() - .try( - Joi.string().pattern(/^\d+(\.\d{1,4})?$/), - Joi.number().positive(), - ) + .try(Joi.string().pattern(/^\d+(\.\d{1,4})?$/), Joi.number().positive()) .required() - .messages({ "alternatives.match": "faceValue must be a positive number or decimal string with max 4 decimal places" }), + .messages({ + "alternatives.match": + "faceValue must be a positive number or decimal string with max 4 decimal places", + }), dueDate: Joi.date().iso().required(), discountBps: Joi.number().integer().min(0).max(10000).required(), platformFeeBps: Joi.number().integer().min(0).max(10000).optional().default(0), @@ -112,9 +122,7 @@ function validateBody(schema: Joi.Schema) { }); if (error) { - return next( - new HttpError(400, `Invalid request: ${error.message}`) - ); + return next(new HttpError(400, `Invalid request: ${error.message}`)); } req.body = value; @@ -130,24 +138,19 @@ function validateQuery(schema: Joi.Schema) { }); if (error) { - return next( - new HttpError(400, `Invalid query parameters: ${error.message}`) - ); + return next(new HttpError(400, `Invalid query parameters: ${error.message}`)); } // Replace req.query with validated value // In Express, req.query is a getter/setter by default, but we can override it // if we use the default query parser. - Object.keys(req.query).forEach(key => delete req.query[key]); + Object.keys(req.query).forEach((key) => delete req.query[key]); Object.assign(req.query, value); next(); }; } -export function createInvoiceRouter({ - invoiceService, - config, -}: InvoiceRouterDependencies): Router { +export function createInvoiceRouter({ invoiceService, config }: InvoiceRouterDependencies): Router { const router = Router(); const controller = createInvoiceController(invoiceService); @@ -185,18 +188,13 @@ export function createInvoiceRouter({ // Per-wallet rate limit: max 5 invoice publishes per 60 seconds const publishRateLimiter = createWalletRateLimiter( { windowMs: 60_000, maxRequests: 5 }, - "invoice-publish", + "invoice-publish" ); // ============ INVOICE CRUD ENDPOINTS ============ // GET /api/v1/invoices - List invoices for authenticated seller - router.get( - "/", - authenticateJWT, - validateQuery(getInvoicesQuerySchema), - controller.getInvoices, - ); + router.get("/", authenticateJWT, validateQuery(getInvoicesQuerySchema), controller.getInvoices); // POST /api/v1/invoices - Create new invoice router.post( @@ -204,7 +202,7 @@ export function createInvoiceRouter({ authenticateJWT, kycGating, validateBody(createInvoiceSchema), - controller.createInvoice, + controller.createInvoice ); // POST /api/v1/invoices/batch-publish - Publish several drafts atomically. @@ -216,7 +214,7 @@ export function createInvoiceRouter({ kycGating, publishRateLimiter, validateBody(batchPublishSchema), - controller.batchPublishInvoices, + controller.batchPublishInvoices ); // GET /api/v1/invoices/:id - Get single invoice @@ -228,7 +226,7 @@ export function createInvoiceRouter({ authenticateJWT, kycGating, validateBody(updateInvoiceSchema), - controller.updateInvoice, + controller.updateInvoice ); // DELETE /api/v1/invoices/:id - Delete invoice @@ -240,7 +238,7 @@ export function createInvoiceRouter({ authenticateJWT, kycGating, publishRateLimiter, - controller.publishInvoice, + controller.publishInvoice ); // POST /api/v1/invoices/:id/document - Upload document @@ -250,29 +248,17 @@ export function createInvoiceRouter({ authenticateJWT, kycGating, upload.single("document"), - controller.uploadDocument, + controller.uploadDocument ); // GET /api/v1/invoices/:id/tokens - Get invoice token holders - router.get( - "/:id/tokens", - authenticateJWT, - controller.getInvoiceTokenHolders, - ); + router.get("/:id/tokens", authenticateJWT, controller.getInvoiceTokenHolders); // GET /api/v1/invoices/:id/escrow - Get invoice escrow status - router.get( - "/:id/escrow", - authenticateJWT, - controller.getInvoiceEscrowStatus, - ); + router.get("/:id/escrow", authenticateJWT, controller.getInvoiceEscrowStatus); // POST /api/v1/invoices/calculate-terms - Calculate invoice discounting terms, fees, and APR - router.post( - "/calculate-terms", - validateBody(calculateTermsSchema), - controller.calculateTerms, - ); + router.post("/calculate-terms", validateBody(calculateTermsSchema), controller.calculateTerms); return router; } diff --git a/src/routes/invoices/publish.ts b/src/routes/invoices/publish.ts index 8e6ea80..f9f6873 100644 --- a/src/routes/invoices/publish.ts +++ b/src/routes/invoices/publish.ts @@ -21,4 +21,4 @@ export async function publishInvoice(req: AuthenticatedRequest, res: Response) { }, }); } -} \ No newline at end of file +} diff --git a/src/routes/kyc.routes.ts b/src/routes/kyc.routes.ts index 6852980..0eb83ee 100644 --- a/src/routes/kyc.routes.ts +++ b/src/routes/kyc.routes.ts @@ -7,7 +7,11 @@ import type { AuthService } from "../services/auth.service"; export function createKycWebhookRouter(service: KycService): Router { const router = Router(); const controller = createKycController(service); - router.post("/webhook", express.raw({ type: "application/json", limit: "256kb" }), controller.webhook); + router.post( + "/webhook", + express.raw({ type: "application/json", limit: "256kb" }), + controller.webhook + ); return router; } diff --git a/src/routes/marketplace.routes.ts b/src/routes/marketplace.routes.ts index 2674395..02224ae 100644 --- a/src/routes/marketplace.routes.ts +++ b/src/routes/marketplace.routes.ts @@ -16,4 +16,4 @@ export function createMarketplaceRouter({ router.get("/invoices", controller.getInvoices); return router; -} \ No newline at end of file +} diff --git a/src/routes/notification.routes.ts b/src/routes/notification.routes.ts index f8e5b11..5c583cc 100644 --- a/src/routes/notification.routes.ts +++ b/src/routes/notification.routes.ts @@ -6,7 +6,7 @@ import type { NotificationService } from "../services/notification.service"; export function createNotificationRouter( notificationService: NotificationService, - authService: AuthService, + authService: AuthService ): Router { const router = Router(); const controller = createNotificationController(notificationService); @@ -28,4 +28,4 @@ export function createNotificationRouter( router.patch("/:id/read", controller.markRead); return router; -} \ No newline at end of file +} diff --git a/src/services/auth.service.ts b/src/services/auth.service.ts index 21fdf0a..dde9c3f 100644 --- a/src/services/auth.service.ts +++ b/src/services/auth.service.ts @@ -7,12 +7,10 @@ import { AuthChallenge } from "../models/AuthChallenge.model"; import { User } from "../models/User.model"; import type { PublicUser } from "../types/auth"; import { HttpError } from "../utils/http-error"; -import { - buildAuthFailureDetails, - classifyJwtError, -} from "../lib/auth-failure"; +import { buildAuthFailureDetails, classifyJwtError } from "../lib/auth-failure"; import type { AppLogger } from "../observability/logger"; import { buildWalletChallenge } from "../utils/stellar-challenge"; +import { MetricsRegistry } from "../observability/metrics"; interface ChallengeRecord { id: string; @@ -37,6 +35,14 @@ interface CreateChallengeRecordInput { export interface UserRepositoryContract { findById(id: string): Promise; findByStellarAddress(stellarAddress: string): Promise; + findByEmail(email: string): Promise; + findAll(options?: { + skip?: number; + take?: number; + cursor?: string; + order?: "ASC" | "DESC"; + }): Promise; + count(options?: { cursor?: string }): Promise; save(user: Partial): Promise; } @@ -44,9 +50,11 @@ export interface ChallengeRepositoryContract { create(input: CreateChallengeRecordInput): Promise; findByAddressAndNonceHash( stellarAddress: string, - nonceHash: string, + nonceHash: string ): Promise; consume(id: string, consumedAt: Date): Promise; + deleteExpired(before: Date): Promise; + countByStatus(status: "active" | "consumed" | "expired"): Promise; } interface AuthTokenPayload extends JwtPayload { @@ -59,6 +67,7 @@ export interface AuthServiceDependencies { challengeRepository: ChallengeRepositoryContract; config: Pick & { serverKeypair?: Keypair }; logger?: AppLogger; + metrics?: MetricsRegistry; } export interface ChallengeResponse { @@ -90,6 +99,7 @@ export class AuthService { private readonly config: Pick; private readonly logger?: AppLogger; private readonly serverKeypair?: Keypair; + private readonly metrics?: MetricsRegistry; constructor(dependencies: AuthServiceDependencies) { this.userRepository = dependencies.userRepository; @@ -97,6 +107,14 @@ export class AuthService { this.config = dependencies.config; this.logger = dependencies.logger; this.serverKeypair = dependencies.config.serverKeypair; + this.metrics = dependencies.metrics; + } + + private recordChallengeMetric( + status: "created" | "verified" | "expired" | "failed" | "reused", + wallet: string + ): void { + this.metrics?.increment("auth_challenge_total", { status, wallet: wallet.slice(0, 8) + "..." }); } async createChallenge(publicKey: string): Promise { @@ -112,7 +130,7 @@ export class AuthService { ({ nonce } = buildWalletChallenge( sanitizedKey, this.config.stellar.networkPassphrase, - this.serverKeypair, + this.serverKeypair )); } else { nonce = crypto.randomBytes(32).toString("hex"); @@ -136,6 +154,7 @@ export class AuthService { issuedAt, expiresAt, }); + this.recordChallengeMetric("created", sanitizedKey); } catch (error) { this.logger?.error("Failed to persist challenge", { error, stellarAddress: sanitizedKey }); throw new HttpError(500, "Failed to create challenge."); @@ -158,9 +177,7 @@ export class AuthService { } } - async verifyChallenge( - input: VerifyChallengeInput, - ): Promise { + async verifyChallenge(input: VerifyChallengeInput): Promise { try { const sanitizedKey = input.publicKey.trim(); const sanitizedNonce = input.nonce.trim(); @@ -179,7 +196,7 @@ export class AuthService { try { challenge = await this.challengeRepository.findByAddressAndNonceHash( sanitizedKey, - hashNonce(sanitizedNonce), + hashNonce(sanitizedNonce) ); } catch (error) { this.logger?.error("Failed to fetch challenge", { error, stellarAddress: sanitizedKey }); @@ -199,6 +216,7 @@ export class AuthService { } if (challenge.expiresAt.getTime() <= Date.now()) { + this.recordChallengeMetric("expired", sanitizedKey); throw new HttpError(401, "Challenge expired."); } @@ -224,6 +242,7 @@ export class AuthService { if (!isValid) { this.logger?.warn("Invalid challenge signature", { stellarAddress: sanitizedKey }); + this.recordChallengeMetric("failed", sanitizedKey); throw new HttpError(401, "Invalid signature."); } @@ -239,6 +258,8 @@ export class AuthService { throw new HttpError(401, "Challenge already used."); } + this.recordChallengeMetric("verified", sanitizedKey); + let user: User; try { user = await this.upsertUser(sanitizedKey); @@ -253,7 +274,9 @@ export class AuthService { const decoded = jwt.decode(token) as { iat?: number; exp?: number } | null; this.logger?.info("jwt.issued", { wallet: publicUser.stellarAddress, - issued_at: decoded?.iat ? new Date(decoded.iat * 1000).toISOString() : new Date().toISOString(), + issued_at: decoded?.iat + ? new Date(decoded.iat * 1000).toISOString() + : new Date().toISOString(), expires_at: decoded?.exp ? new Date(decoded.exp * 1000).toISOString() : null, ip_address: input.ipAddress ?? null, }); @@ -273,12 +296,46 @@ export class AuthService { } } + async cleanupExpiredChallenges(maxAgeMs = 24 * 60 * 60 * 1000): Promise { + const before = new Date(Date.now() - maxAgeMs); + try { + const deleted = await this.challengeRepository.deleteExpired(before); + this.logger?.info("Cleaned up expired challenges", { count: deleted }); + return deleted; + } catch (error) { + this.logger?.error("Failed to cleanup expired challenges", { error }); + throw new HttpError(500, "Failed to cleanup expired challenges."); + } + } + + async getChallengeMetrics(): Promise<{ + active: number; + consumed: number; + expired: number; + }> { + try { + const [active, consumed, expired] = await Promise.all([ + this.challengeRepository.countByStatus("active"), + this.challengeRepository.countByStatus("consumed"), + this.challengeRepository.countByStatus("expired"), + ]); + return { active, consumed, expired }; + } catch (error) { + this.logger?.error("Failed to get challenge metrics", { error }); + throw new HttpError(500, "Failed to get challenge metrics."); + } + } + async getCurrentUser(token: string): Promise { let payload: AuthTokenPayload; const sanitizedToken = token?.trim(); if (!sanitizedToken) { - throw new HttpError(401, "Invalid or expired token.", buildAuthFailureDetails(token, "missing_token")); + throw new HttpError( + 401, + "Invalid or expired token.", + buildAuthFailureDetails(token, "missing_token") + ); } try { @@ -287,7 +344,7 @@ export class AuthService { throw new HttpError( 401, "Invalid or expired token.", - buildAuthFailureDetails(sanitizedToken, classifyJwtError(error)), + buildAuthFailureDetails(sanitizedToken, classifyJwtError(error)) ); } @@ -295,7 +352,7 @@ export class AuthService { throw new HttpError( 401, "Invalid token payload.", - buildAuthFailureDetails(sanitizedToken, "invalid_token"), + buildAuthFailureDetails(sanitizedToken, "invalid_token") ); } @@ -321,8 +378,8 @@ export class AuthService { } private async upsertUser(publicKey: string): Promise { + const sanitized = publicKey.trim(); try { - const sanitized = publicKey.trim(); const existingUser = await this.userRepository.findByStellarAddress(sanitized); if (existingUser) { @@ -333,6 +390,10 @@ export class AuthService { stellarAddress: sanitized, }); } catch (error) { + if (error instanceof Error && error.message.includes("duplicate key")) { + const existing = await this.userRepository.findByStellarAddress(sanitized); + if (existing) return existing; + } this.logger?.error("upsertUser failed", { error, publicKey }); throw error; } @@ -352,13 +413,13 @@ export class AuthService { { ...signOptions, subject: user.stellarAddress, - }, + } ); } } class TypeOrmUserRepository implements UserRepositoryContract { - constructor(private readonly repository: Repository) { } + constructor(private readonly repository: Repository) {} findById(id: string): Promise { return this.repository.findOne({ @@ -372,6 +433,42 @@ class TypeOrmUserRepository implements UserRepositoryContract { }); } + findByEmail(email: string): Promise { + return this.repository.findOne({ + where: { email }, + }); + } + + findAll(options?: { + skip?: number; + take?: number; + cursor?: string; + order?: "ASC" | "DESC"; + }): Promise { + const qb = this.repository.createQueryBuilder("user"); + qb.where("user.deletedAt IS NULL"); + + if (options?.cursor) { + const direction = options.order === "ASC" ? ">" : "<"; + qb.andWhere(`user.id ${direction} :cursor`, { cursor: options.cursor }); + } + + qb.orderBy("user.id", options?.order ?? "DESC"); + if (options?.take) qb.take(options.take); + if (options?.skip) qb.skip(options.skip); + + return qb.getMany(); + } + + async count(options?: { cursor?: string }): Promise { + const qb = this.repository.createQueryBuilder("user"); + qb.where("user.deletedAt IS NULL"); + if (options?.cursor) { + qb.andWhere("user.id < :cursor", { cursor: options.cursor }); + } + return qb.getCount(); + } + async save(user: Partial): Promise { const entity = this.repository.create(user); return this.repository.save(entity); @@ -379,7 +476,7 @@ class TypeOrmUserRepository implements UserRepositoryContract { } class TypeOrmChallengeRepository implements ChallengeRepositoryContract { - constructor(private readonly repository: Repository) { } + constructor(private readonly repository: Repository) {} async create(input: CreateChallengeRecordInput): Promise { const entity = this.repository.create({ @@ -397,7 +494,7 @@ class TypeOrmChallengeRepository implements ChallengeRepositoryContract { findByAddressAndNonceHash( stellarAddress: string, - nonceHash: string, + nonceHash: string ): Promise { return this.repository.findOne({ where: { @@ -415,25 +512,52 @@ class TypeOrmChallengeRepository implements ChallengeRepositoryContract { }, { consumedAt, - }, + } ); return (result.affected ?? 0) > 0; } + + async deleteExpired(before: Date): Promise { + const result = await this.repository + .createQueryBuilder() + .delete() + .where("expiresAt < :before", { before }) + .orWhere("consumedAt IS NOT NULL AND consumedAt < :before", { before }) + .execute(); + return result.affected ?? 0; + } + + async countByStatus(status: "active" | "consumed" | "expired"): Promise { + const qb = this.repository.createQueryBuilder("challenge"); + const now = new Date(); + switch (status) { + case "active": + qb.where("challenge.consumedAt IS NULL AND challenge.expiresAt > :now", { now }); + break; + case "consumed": + qb.where("challenge.consumedAt IS NOT NULL"); + break; + case "expired": + qb.where("challenge.consumedAt IS NULL AND challenge.expiresAt <= :now", { now }); + break; + } + return qb.getCount(); + } } export function createAuthService( dataSource: DataSource, config: Pick, logger?: AppLogger, + metrics?: MetricsRegistry ): AuthService { return new AuthService({ userRepository: new TypeOrmUserRepository(dataSource.getRepository(User)), - challengeRepository: new TypeOrmChallengeRepository( - dataSource.getRepository(AuthChallenge), - ), + challengeRepository: new TypeOrmChallengeRepository(dataSource.getRepository(AuthChallenge)), config, logger, + metrics, }); } @@ -473,10 +597,7 @@ function decodeSignature(signature: string): Buffer { ? trimmedSignature.slice(2) : trimmedSignature; - if ( - /^[a-fA-F0-9]+$/.test(normalizedHexSignature) && - normalizedHexSignature.length % 2 === 0 - ) { + if (/^[a-fA-F0-9]+$/.test(normalizedHexSignature) && normalizedHexSignature.length % 2 === 0) { return Buffer.from(normalizedHexSignature, "hex"); } @@ -484,9 +605,7 @@ function decodeSignature(signature: string): Buffer { throw new HttpError(400, "Signature must be base64, base64url, or hex encoded."); } - const normalizedBase64Signature = trimmedSignature - .replace(/-/g, "+") - .replace(/_/g, "/"); + const normalizedBase64Signature = trimmedSignature.replace(/-/g, "+").replace(/_/g, "/"); const paddingLength = normalizedBase64Signature.length % 4; const paddedBase64Signature = paddingLength === 0 diff --git a/src/services/investment.service.ts b/src/services/investment.service.ts index 34a2434..6d909b9 100644 --- a/src/services/investment.service.ts +++ b/src/services/investment.service.ts @@ -84,35 +84,35 @@ export class InvestmentService { let failedCount = 0; for (const investment of investments) { - const amount = new Decimal(investment.investmentAmount); - totalInvested = totalInvested.plus(amount); + const amount = new Decimal(investment.investmentAmount); + totalInvested = totalInvested.plus(amount); if (ACTIVE_INVESTMENT_STATUSES.includes(investment.status)) { - activeCount += 1; - activeTotal = activeTotal.plus(amount); - } - - if (SETTLED_INVESTMENT_STATUSES.includes(investment.status)) { - settledCount += 1; - if (investment.actualReturn !== null) { - totalReturns = totalReturns.plus(new Decimal(investment.actualReturn)); - } - } - - if (FAILED_INVESTMENT_STATUSES.includes(investment.status)) { - failedCount += 1; - } + activeCount += 1; + activeTotal = activeTotal.plus(amount); + } + + if (SETTLED_INVESTMENT_STATUSES.includes(investment.status)) { + settledCount += 1; + if (investment.actualReturn !== null) { + totalReturns = totalReturns.plus(new Decimal(investment.actualReturn)); + } + } + + if (FAILED_INVESTMENT_STATUSES.includes(investment.status)) { + failedCount += 1; + } } return { - totalInvested: totalInvested.toFixed(4), - totalReturns: totalReturns.toFixed(4), - activeInvestments: activeCount, - activeCount, - activeTotal: activeTotal.toFixed(4), - settledCount, - settledReturns: totalReturns.toFixed(4), - failedCount, + totalInvested: totalInvested.toFixed(4), + totalReturns: totalReturns.toFixed(4), + activeInvestments: activeCount, + activeCount, + activeTotal: activeTotal.toFixed(4), + settledCount, + settledReturns: totalReturns.toFixed(4), + failedCount, }; } @@ -193,9 +193,10 @@ export class InvestmentService { // Settled returns if (SETTLED_INVESTMENT_STATUSES.includes(investment.status)) { - const actualReturn = investment.actualReturn !== null && investment.actualReturn !== undefined - ? new Decimal(investment.actualReturn) - : expectedReturn; + const actualReturn = + investment.actualReturn !== null && investment.actualReturn !== undefined + ? new Decimal(investment.actualReturn) + : expectedReturn; const profit = actualReturn.minus(amount); if (profit.gt(0)) { totalProfitEarned = totalProfitEarned.plus(profit); @@ -222,9 +223,10 @@ export class InvestmentService { monthEntry.invested = monthEntry.invested.plus(amount); if (investment.status === InvestmentStatus.SETTLED) { - const actualReturn = investment.actualReturn !== null && investment.actualReturn !== undefined - ? new Decimal(investment.actualReturn) - : expectedReturn; + const actualReturn = + investment.actualReturn !== null && investment.actualReturn !== undefined + ? new Decimal(investment.actualReturn) + : expectedReturn; monthEntry.returned = monthEntry.returned.plus(actualReturn); const profit = actualReturn.minus(amount); if (profit.gt(0)) { @@ -246,9 +248,7 @@ export class InvestmentService { ? weightedYieldSum.dividedBy(totalDeployedCapital).toFixed(2) : "0.00"; - const projectedTotalReturn = pendingPayouts.gt(0) - ? pendingPayouts - : totalDeployedCapital; + const projectedTotalReturn = pendingPayouts.gt(0) ? pendingPayouts : totalDeployedCapital; const monthlyPerformance: MonthlyYieldMetric[] = Array.from(monthlyMap.entries()).map( ([month, data]) => ({ @@ -258,7 +258,7 @@ export class InvestmentService { profit: data.profit.toFixed(4), averageYieldPercent: data.count > 0 ? data.yieldSum.dividedBy(data.count).toFixed(2) : "0.00", - }), + }) ); return { @@ -310,7 +310,7 @@ export class InvestmentService { if (invoice.status !== InvoiceStatus.PUBLISHED) { throw new ServiceError( "INVALID_INVOICE_STATUS", - `Cannot invest in an invoice with status ${invoice.status}`, + `Cannot invest in an invoice with status ${invoice.status}` ); } @@ -319,7 +319,7 @@ export class InvestmentService { throw new ServiceError( "invoice_expired", "Invoice has passed its due date and is no longer accepting investments", - 422, + 422 ); } @@ -339,7 +339,7 @@ export class InvestmentService { const totalInvested = activeInvestments.reduce( (sum, inv) => sum.plus(new Decimal(inv.investmentAmount)), - new Decimal(0), + new Decimal(0) ); const netAmount = new Decimal(invoice.netAmount); @@ -348,7 +348,7 @@ export class InvestmentService { if (amount.gt(remainingCapacity)) { throw new ServiceError( "INSUFFICIENT_CAPACITY", - `Investment amount ${amount.toString()} exceeds remaining capacity ${remainingCapacity.toString()}`, + `Investment amount ${amount.toString()} exceeds remaining capacity ${remainingCapacity.toString()}` ); } diff --git a/src/services/invoice.service.ts b/src/services/invoice.service.ts index f01d238..7cf3d50 100644 --- a/src/services/invoice.service.ts +++ b/src/services/invoice.service.ts @@ -36,7 +36,7 @@ export interface NotificationSink { userId: string, type: NotificationType, title: string, - message: string, + message: string ): Promise; } @@ -148,7 +148,11 @@ export interface GetInvoicesOptions { */ const VALID_TRANSITIONS: Record = { [InvoiceStatus.DRAFT]: [InvoiceStatus.PENDING, InvoiceStatus.PUBLISHED, InvoiceStatus.CANCELLED], - [InvoiceStatus.PENDING]: [InvoiceStatus.PUBLISHED, InvoiceStatus.CANCELLED, InvoiceStatus.REJECTED], + [InvoiceStatus.PENDING]: [ + InvoiceStatus.PUBLISHED, + InvoiceStatus.CANCELLED, + InvoiceStatus.REJECTED, + ], [InvoiceStatus.PUBLISHED]: [InvoiceStatus.FUNDED, InvoiceStatus.CANCELLED], [InvoiceStatus.FUNDED]: [InvoiceStatus.SETTLED, InvoiceStatus.CANCELLED], [InvoiceStatus.SETTLED]: [], @@ -185,7 +189,13 @@ export class InvoiceService { try { const amt = new Decimal(amount); const disc = new Decimal(discountRate); - if (!amt.isFinite() || !disc.isFinite() || amt.isNegative() || disc.isNegative() || disc.gt(100)) { + if ( + !amt.isFinite() || + !disc.isFinite() || + amt.isNegative() || + disc.isNegative() || + disc.gt(100) + ) { throw new ServiceError("invalid_amount", "Invalid amount or discount rate", 400); } const netAmount = amt.minus(amt.times(disc.dividedBy(100))); @@ -462,7 +472,7 @@ export class InvoiceService { throw new ServiceError( "invoice_not_publishable", `Invoice failed pre-publish validation: ${validationErrors.map((e) => e.message).join(" ")}`, - 400, + 400 ); } @@ -495,7 +505,7 @@ export class InvoiceService { * on each retry. */ async publishInvoicesBatch( - input: BatchPublishInvoicesInput, + input: BatchPublishInvoicesInput ): Promise { const { invoiceIds, sellerId } = input; @@ -509,7 +519,7 @@ export class InvoiceService { throw new ServiceError( "batch_publish_unavailable", "Batch publishing requires a database connection", - 503, + 503 ); } @@ -529,11 +539,15 @@ export class InvoiceService { where: { id: invoiceId }, relations: ["seller"], }), - })), + })) ); } catch (error) { logger.error("Failed to fetch batch invoices", { error, sellerId }); - throw new ServiceError("batch_fetch_failed", "Failed to fetch invoices for batch publish", 500); + throw new ServiceError( + "batch_fetch_failed", + "Failed to fetch invoices for batch publish", + 500 + ); } for (const { invoiceId, invoice } of fetched) { @@ -560,7 +574,7 @@ export class InvoiceService { throw new ServiceError( "kyc_approval_required", "KYC approval is required to publish invoices", - 403, + 403 ); } @@ -591,7 +605,7 @@ export class InvoiceService { "batch_publish_rejected", `${rejections.length} of ${uniqueIds.length} invoices cannot be published; no invoices were changed`, 400, - { rejections }, + { rejections } ); } @@ -710,11 +724,7 @@ export class InvoiceService { } if (!this.dataSource) { - throw new ServiceError( - "internal_error", - "Database connection unavailable", - 500 - ); + throw new ServiceError("internal_error", "Database connection unavailable", 500); } const investmentRepository = this.dataSource.getRepository(Investment); diff --git a/src/services/kyc.service.ts b/src/services/kyc.service.ts index c7ee964..014faf7 100644 --- a/src/services/kyc.service.ts +++ b/src/services/kyc.service.ts @@ -24,10 +24,13 @@ export class KycService { constructor( private readonly dataSource: DataSource, private readonly webhookSecret: string, - private readonly appLogger: AppLogger = logger, + private readonly appLogger: AppLogger = logger ) {} - async submitKycVerification(userId: string, providerData: KycProviderData = {}): Promise { + async submitKycVerification( + userId: string, + providerData: KycProviderData = {} + ): Promise { return this.dataSource.transaction(async (manager) => { const user = await manager.getRepository(User).findOneBy({ id: userId }); if (!user) throw new HttpError(404, "User not found."); @@ -37,10 +40,16 @@ export class KycService { userId, verificationType: providerData.verificationType ?? KYCVerificationType.IDENTITY, status: KYCStatus.PENDING, - documents: providerData.documents ?? (providerData.providerReference ? { providerReference: providerData.providerReference } : null), + documents: + providerData.documents ?? + (providerData.providerReference + ? { providerReference: providerData.providerReference } + : null), }); const saved = await repository.save(verification); - await manager.getRepository(User).update(userId, { kycStatus: KYCStatus.PENDING, isKycVerified: false }); + await manager + .getRepository(User) + .update(userId, { kycStatus: KYCStatus.PENDING, isKycVerified: false }); return saved; }); } @@ -51,7 +60,10 @@ export class KycService { const expected = crypto.createHmac("sha256", this.webhookSecret).update(rawBody).digest("hex"); const suppliedBuffer = Buffer.from(supplied, "hex"); const expectedBuffer = Buffer.from(expected, "hex"); - return suppliedBuffer.length === expectedBuffer.length && crypto.timingSafeEqual(suppliedBuffer, expectedBuffer); + return ( + suppliedBuffer.length === expectedBuffer.length && + crypto.timingSafeEqual(suppliedBuffer, expectedBuffer) + ); } async processWebhook(payload: KycWebhookPayload): Promise { diff --git a/src/services/marketplace.service.ts b/src/services/marketplace.service.ts index f81d7d1..1bbd356 100644 --- a/src/services/marketplace.service.ts +++ b/src/services/marketplace.service.ts @@ -59,7 +59,7 @@ export interface MarketplaceCursorPage { export interface MarketplaceRepositoryContract { findPublishedInvoices( filters: MarketplaceFilters, - pagination: PaginationOptions, + pagination: PaginationOptions ): Promise<{ invoices: Invoice[]; total: number }>; /** * Optional so that existing fake repositories implementing this contract @@ -69,7 +69,7 @@ export interface MarketplaceRepositoryContract { */ findPublishedInvoicesByCursor?( filters: MarketplaceFilters, - pagination: CursorPaginationOptions, + pagination: CursorPaginationOptions ): Promise<{ invoices: Invoice[]; nextCursor: string | null; hasMore: boolean }>; } @@ -86,7 +86,7 @@ export class MarketplaceService { async getPublishedInvoices( filters: MarketplaceFilters = {}, - pagination: PaginationOptions = { page: 1, limit: 20 }, + pagination: PaginationOptions = { page: 1, limit: 20 } ): Promise { // Set default filters const normalizedFilters: MarketplaceFilters = { @@ -107,7 +107,7 @@ export class MarketplaceService { const { invoices, total } = await this.marketplaceRepository.findPublishedInvoices( normalizedFilters, - normalizedPagination, + normalizedPagination ); const publicInvoices: PublicInvoice[] = invoices.map(this.toPublicInvoice); @@ -132,7 +132,7 @@ export class MarketplaceService { */ async getPublishedInvoicesByCursor( filters: MarketplaceFilters = {}, - pagination: CursorPaginationOptions, + pagination: CursorPaginationOptions ): Promise { const normalizedFilters: MarketplaceFilters = { status: filters.status || [InvoiceStatus.PUBLISHED], @@ -146,7 +146,7 @@ export class MarketplaceService { if (!this.marketplaceRepository.findPublishedInvoicesByCursor) { throw new Error( - "getPublishedInvoicesByCursor: the configured MarketplaceRepositoryContract does not implement findPublishedInvoicesByCursor", + "getPublishedInvoicesByCursor: the configured MarketplaceRepositoryContract does not implement findPublishedInvoicesByCursor" ); } @@ -189,7 +189,7 @@ class TypeORMMarketplaceRepository implements MarketplaceRepositoryContract { async findPublishedInvoices( filters: MarketplaceFilters, - pagination: PaginationOptions, + pagination: PaginationOptions ): Promise<{ invoices: Invoice[]; total: number }> { const queryBuilder = this.repository .createQueryBuilder("invoice") @@ -278,7 +278,7 @@ class TypeORMMarketplaceRepository implements MarketplaceRepositoryContract { async findPublishedInvoicesByCursor( filters: MarketplaceFilters, - pagination: CursorPaginationOptions, + pagination: CursorPaginationOptions ): Promise<{ invoices: Invoice[]; nextCursor: string | null; hasMore: boolean }> { const queryBuilder = this.repository .createQueryBuilder("invoice") @@ -335,4 +335,4 @@ export function createMarketplaceService(dataSource: DataSource): MarketplaceSer return new MarketplaceService({ marketplaceRepository, }); -} \ No newline at end of file +} diff --git a/src/services/notification.service.ts b/src/services/notification.service.ts index 1a15630..a2d65d8 100644 --- a/src/services/notification.service.ts +++ b/src/services/notification.service.ts @@ -30,7 +30,7 @@ export interface NotificationRepositoryContract { userId: string, type: NotificationType, title: string, - message: string, + message: string ): Promise; findByIdAndUserId(id: string, userId: string): Promise; markRead(id: string, userId: string): Promise; @@ -38,9 +38,7 @@ export interface NotificationRepositoryContract { } export class NotificationService { - constructor( - private readonly notificationRepository: NotificationRepositoryContract, - ) {} + constructor(private readonly notificationRepository: NotificationRepositoryContract) {} /** * Creates a notification for a user. @@ -53,24 +51,19 @@ export class NotificationService { userId: string, type: NotificationType, title: string, - message: string, + message: string ): Promise { return this.notificationRepository.create(userId, type, title, message); } - async listNotifications( - options: ListNotificationsOptions, - ): Promise { + async listNotifications(options: ListNotificationsOptions): Promise { return this.notificationRepository.list(options); } - async markNotificationRead( - notificationId: string, - userId: string, - ): Promise { + async markNotificationRead(notificationId: string, userId: string): Promise { const notification = await this.notificationRepository.findByIdAndUserId( notificationId, - userId, + userId ); if (!notification) { @@ -92,7 +85,7 @@ class TypeOrmNotificationRepository implements NotificationRepositoryContract { userId: string, type: NotificationType, title: string, - message: string, + message: string ): Promise { const entity = this.repository.create({ userId, type, title, message }); return this.repository.save(entity); @@ -112,15 +105,7 @@ class TypeOrmNotificationRepository implements NotificationRepositoryContract { } async list(options: ListNotificationsOptions): Promise { - const { - userId, - page = 1, - limit = 20, - read, - type, - sortOrder = "desc", - cursor, - } = options; + const { userId, page = 1, limit = 20, read, type, sortOrder = "desc", cursor } = options; const qb = this.repository .createQueryBuilder("n") @@ -131,14 +116,22 @@ class TypeOrmNotificationRepository implements NotificationRepositoryContract { if (cursor) { const decoded = Buffer.from(cursor, "base64").toString("utf8").split("::"); - if (decoded.length !== 2 || !decoded[0] || !decoded[1] || Number.isNaN(Date.parse(decoded[0]))) { + if ( + decoded.length !== 2 || + !decoded[0] || + !decoded[1] || + Number.isNaN(Date.parse(decoded[0])) + ) { throw new HttpError(400, "Invalid notification cursor."); } const operator = sortOrder === "asc" ? ">" : "<"; - qb.andWhere(`(n.timestamp ${operator} :cursorTimestamp OR (n.timestamp = :cursorTimestamp AND n.id ${operator} :cursorId))`, { - cursorTimestamp: new Date(decoded[0]), - cursorId: decoded[1], - }); + qb.andWhere( + `(n.timestamp ${operator} :cursorTimestamp OR (n.timestamp = :cursorTimestamp AND n.id ${operator} :cursorId))`, + { + cursorTimestamp: new Date(decoded[0]), + cursorId: decoded[1], + } + ); } else { qb.skip((page - 1) * limit); } @@ -155,9 +148,10 @@ class TypeOrmNotificationRepository implements NotificationRepositoryContract { const hasMore = rows.length > limit; const data = rows.slice(0, limit); const last = data[data.length - 1]; - const nextCursor = hasMore && last - ? Buffer.from(`${last.timestamp.toISOString()}::${last.id}`).toString("base64") - : null; + const nextCursor = + hasMore && last + ? Buffer.from(`${last.timestamp.toISOString()}::${last.id}`).toString("base64") + : null; return { data, @@ -175,6 +169,6 @@ class TypeOrmNotificationRepository implements NotificationRepositoryContract { export function createNotificationService(dataSource: DataSource): NotificationService { return new NotificationService( - new TypeOrmNotificationRepository(dataSource.getRepository(Notification)), + new TypeOrmNotificationRepository(dataSource.getRepository(Notification)) ); } diff --git a/src/services/settlement.service.ts b/src/services/settlement.service.ts index 49dfa24..933d949 100644 --- a/src/services/settlement.service.ts +++ b/src/services/settlement.service.ts @@ -25,7 +25,10 @@ export interface SettleInvoiceInput { actorWallet: string; } -export interface PaymentDistributorSettlementConfig { feeRecipient: string; feeBps: number; } +export interface PaymentDistributorSettlementConfig { + feeRecipient: string; + feeBps: number; +} export interface InvestorSettlement { investmentId: string; @@ -43,7 +46,11 @@ export interface SettleInvoiceResult { } export class SettlementService { - constructor(private readonly dataSource: DataSource, private readonly paymentDistributor?: PaymentDistributorContractService, private readonly distributorConfig?: PaymentDistributorSettlementConfig) {} + constructor( + private readonly dataSource: DataSource, + private readonly paymentDistributor?: PaymentDistributorContractService, + private readonly distributorConfig?: PaymentDistributorSettlementConfig + ) {} /** * Settles a funded invoice by distributing proceeds to each investor @@ -54,10 +61,7 @@ export class SettlementService { const proceeds = new Decimal(proceedsInput); if (proceeds.isNegative() || proceeds.isZero()) { - throw new ServiceError( - "INVALID_PROCEEDS", - "Settlement proceeds must be greater than zero", - ); + throw new ServiceError("INVALID_PROCEEDS", "Settlement proceeds must be greater than zero"); } return await this.dataSource.transaction(async (transactionalEntityManager: EntityManager) => { @@ -85,7 +89,7 @@ export class SettlementService { if (invoice.status !== InvoiceStatus.FUNDED) { throw new ServiceError( "INVALID_INVOICE_STATUS", - `INVALID_INVOICE_STATUS: Cannot settle an invoice with status ${invoice.status}`, + `INVALID_INVOICE_STATUS: Cannot settle an invoice with status ${invoice.status}` ); } @@ -98,14 +102,14 @@ export class SettlementService { if (investments.length === 0) { throw new ServiceError( "NO_CONFIRMED_INVESTMENTS", - "Invoice has no confirmed investments to settle", + "Invoice has no confirmed investments to settle" ); } // 4. Distribute proceeds pro-rata to each investor's share of the total funded amount const totalFunded = investments.reduce( (sum, investment) => sum.plus(new Decimal(investment.investmentAmount)), - new Decimal(0), + new Decimal(0) ); const totalFundedScaled = decimalStringToScaledBigInt(totalFunded.toFixed(4)); const proceedsScaled = decimalStringToScaledBigInt(proceeds.toFixed(4)); @@ -118,7 +122,10 @@ export class SettlementService { if (this.paymentDistributor) { if (!this.distributorConfig) { - throw new ServiceError("DISTRIBUTOR_CONFIGURATION_MISSING", "Payment distributor fee configuration is required"); + throw new ServiceError( + "DISTRIBUTOR_CONFIGURATION_MISSING", + "Payment distributor fee configuration is required" + ); } const distribution = await this.paymentDistributor.distributePayouts({ invoiceId: invoice.id, @@ -127,20 +134,28 @@ export class SettlementService { feeBps: this.distributorConfig.feeBps, recipients: investments.map((investment) => ({ address: investment.investor?.stellarAddress ?? investment.investorId, - amountStroops: computeInvestorReturn(decimalStringToScaledBigInt(investment.investmentAmount), totalFundedScaled, distributableScaled) * DECIMAL_SCALE_TO_STROOP_FACTOR, + amountStroops: + computeInvestorReturn( + decimalStringToScaledBigInt(investment.investmentAmount), + totalFundedScaled, + distributableScaled + ) * DECIMAL_SCALE_TO_STROOP_FACTOR, })), }); distributionTransactionHash = distribution.transactionHash; - await transactionalEntityManager.save(Transaction, transactionalEntityManager.create(Transaction, { - userId: invoice.sellerId, - invoiceId: invoice.id, - investmentId: null, - type: TransactionType.PAYMENT, - amount: proceeds.toFixed(4), - stellarTxHash: distribution.transactionHash, - stellarOperationIndex: 0, - status: TransactionStatus.COMPLETED, - })); + await transactionalEntityManager.save( + Transaction, + transactionalEntityManager.create(Transaction, { + userId: invoice.sellerId, + invoiceId: invoice.id, + investmentId: null, + type: TransactionType.PAYMENT, + amount: proceeds.toFixed(4), + stellarTxHash: distribution.transactionHash, + stellarOperationIndex: 0, + status: TransactionStatus.COMPLETED, + }) + ); } for (const investment of investments) { @@ -148,7 +163,7 @@ export class SettlementService { const actualReturnScaled = computeInvestorReturn( investmentAmountScaled, totalFundedScaled, - distributableScaled, + distributableScaled ); investment.actualReturn = scaledBigIntToDecimalString(actualReturnScaled); @@ -193,6 +208,10 @@ export class SettlementService { } } -export function createSettlementService(dataSource: DataSource, paymentDistributor?: PaymentDistributorContractService, distributorConfig?: PaymentDistributorSettlementConfig): SettlementService { +export function createSettlementService( + dataSource: DataSource, + paymentDistributor?: PaymentDistributorContractService, + distributorConfig?: PaymentDistributorSettlementConfig +): SettlementService { return new SettlementService(dataSource, paymentDistributor, distributorConfig); } diff --git a/src/services/stellar/contract-guard.service.ts b/src/services/stellar/contract-guard.service.ts index 999aad3..6e89d4d 100644 --- a/src/services/stellar/contract-guard.service.ts +++ b/src/services/stellar/contract-guard.service.ts @@ -190,7 +190,7 @@ export function buildPausedLedgerKey(contractId: string): string { contract: new Address(contractId).toScAddress(), key: xdr.ScVal.scvSymbol(PAUSED_STORAGE_KEY), durability: xdr.ContractDataDurability.persistent(), - }), + }) ); return key.toXDR("base64"); } @@ -209,7 +209,7 @@ export function decodePausedEntry(entryXdr: string): boolean { } export function createContractGuardService( - dependencies: ContractGuardServiceDependencies, + dependencies: ContractGuardServiceDependencies ): ContractGuardService { return new ContractGuardService(dependencies); } diff --git a/src/services/stellar/event-indexer.service.ts b/src/services/stellar/event-indexer.service.ts index 5a50fc3..f301a24 100644 --- a/src/services/stellar/event-indexer.service.ts +++ b/src/services/stellar/event-indexer.service.ts @@ -114,17 +114,18 @@ export class EventIndexerService { const contractIdStr = rawEvent.contractId ? typeof rawRecord.contractId === "string" ? (rawRecord.contractId as string) - : typeof (rawEvent.contractId as unknown as { contractId?: () => string }).contractId === "function" - ? (rawEvent.contractId as unknown as { contractId: () => string }).contractId() - : String(rawEvent.contractId) + : typeof (rawEvent.contractId as unknown as { contractId?: () => string }).contractId === + "function" + ? (rawEvent.contractId as unknown as { contractId: () => string }).contractId() + : String(rawEvent.contractId) : ""; const txHash = typeof rawRecord.txHash === "string" ? rawRecord.txHash : typeof rawRecord.pagingToken === "string" - ? rawRecord.pagingToken - : rawEvent.id; + ? rawRecord.pagingToken + : rawEvent.id; return { id: rawEvent.id, @@ -142,11 +143,8 @@ export class EventIndexerService { /** * Polls contract events from Soroban RPC matching configured contract IDs. */ - public async pollContractEvents( - options: PollEventsOptions = {}, - ): Promise { - const startLedger = - options.startLedger ?? (await this.getLastIndexedLedger()) + 1; + public async pollContractEvents(options: PollEventsOptions = {}): Promise { + const startLedger = options.startLedger ?? (await this.getLastIndexedLedger()) + 1; try { const filters = [ @@ -219,7 +217,7 @@ export class EventIndexerService { if (this.eventLogRepository) { await this.eventLogRepository.update( { txHash: event.txHash, topic: event.topic }, - { processed: true }, + { processed: true } ); } diff --git a/src/services/stellar/invoice-escrow-contract.service.ts b/src/services/stellar/invoice-escrow-contract.service.ts index 05bb8de..0ec44cf 100644 --- a/src/services/stellar/invoice-escrow-contract.service.ts +++ b/src/services/stellar/invoice-escrow-contract.service.ts @@ -20,12 +20,7 @@ import type { } from "../../types/soroban.types"; export type CreateEscrowInput = CreateEscrowParams; -export type { - CreateEscrowResult, - FundEscrowParams, - RecordPaymentParams, - SettleEscrowParams, -}; +export type { CreateEscrowResult, FundEscrowParams, RecordPaymentParams, SettleEscrowParams }; export interface InvoiceEscrowContractServiceDependencies { contractId: string; @@ -46,7 +41,7 @@ export class InvoiceEscrowContractService { constructor( dependenciesOrContractId: string | InvoiceEscrowContractServiceDependencies, - logger?: AppLogger, + logger?: AppLogger ) { if (typeof dependenciesOrContractId === "string") { if (!dependenciesOrContractId) { @@ -82,10 +77,9 @@ export class InvoiceEscrowContractService { sellerAddress: string, amountStroops: bigint | number | string, dueDateTimestamp: number, - paymentTokenAddress: string, + paymentTokenAddress: string ): xdr.Operation { - const amountBigInt = - typeof amountStroops === "bigint" ? amountStroops : BigInt(amountStroops); + const amountBigInt = typeof amountStroops === "bigint" ? amountStroops : BigInt(amountStroops); return this.contract.call( "create_escrow", @@ -93,7 +87,7 @@ export class InvoiceEscrowContractService { new Address(sellerAddress).toScVal(), nativeToScVal(amountBigInt, { type: "i128" }), nativeToScVal(dueDateTimestamp, { type: "u64" }), - new Address(paymentTokenAddress).toScVal(), + new Address(paymentTokenAddress).toScVal() ); } @@ -103,16 +97,15 @@ export class InvoiceEscrowContractService { public buildFundEscrowTx( invoiceId: string, investorAddress: string, - amountStroops: bigint | number | string, + amountStroops: bigint | number | string ): xdr.Operation { - const amountBigInt = - typeof amountStroops === "bigint" ? amountStroops : BigInt(amountStroops); + const amountBigInt = typeof amountStroops === "bigint" ? amountStroops : BigInt(amountStroops); return this.contract.call( "fund_escrow", nativeToScVal(invoiceId, { type: "symbol" }), new Address(investorAddress).toScVal(), - nativeToScVal(amountBigInt, { type: "i128" }), + nativeToScVal(amountBigInt, { type: "i128" }) ); } @@ -122,16 +115,15 @@ export class InvoiceEscrowContractService { public buildRecordPaymentTx( invoiceId: string, payerAddress: string, - amountStroops: bigint | number | string, + amountStroops: bigint | number | string ): xdr.Operation { - const amountBigInt = - typeof amountStroops === "bigint" ? amountStroops : BigInt(amountStroops); + const amountBigInt = typeof amountStroops === "bigint" ? amountStroops : BigInt(amountStroops); return this.contract.call( "record_payment", nativeToScVal(invoiceId, { type: "symbol" }), new Address(payerAddress).toScVal(), - nativeToScVal(amountBigInt, { type: "i128" }), + nativeToScVal(amountBigInt, { type: "i128" }) ); } @@ -139,17 +131,14 @@ export class InvoiceEscrowContractService { * Build the Soroban contract invocation operation for settling an escrow. */ public buildSettleEscrowTx(invoiceId: string): xdr.Operation { - return this.contract.call( - "settle_escrow", - nativeToScVal(invoiceId, { type: "symbol" }), - ); + return this.contract.call("settle_escrow", nativeToScVal(invoiceId, { type: "symbol" })); } /** * Simulates a transaction against the Soroban RPC endpoint to verify resource limits and auth footprint. */ public async simulateTransaction( - transaction: Transaction | FeeBumpTransaction, + transaction: Transaction | FeeBumpTransaction ): Promise { if (!this.rpcServer) { throw new Error("Soroban RPC server is not configured for simulation."); @@ -183,7 +172,7 @@ export class InvoiceEscrowContractService { * Submits a transaction to the Stellar network via Soroban RPC sendTransaction. */ public async submitTransaction( - transaction: Transaction | FeeBumpTransaction, + transaction: Transaction | FeeBumpTransaction ): Promise { if (!this.rpcServer) { throw new Error("Soroban RPC server is not configured for submission."); @@ -202,20 +191,16 @@ export class InvoiceEscrowContractService { * Ensures that only sanitized metadata (invoiceId, sorobanContractId, sellerAddress, amountStroops) * is logged without leaking any secret keys, signing seeds, or auth tokens. */ - public async createEscrowOnChain( - input: CreateEscrowInput, - ): Promise { + public async createEscrowOnChain(input: CreateEscrowInput): Promise { const amountBigInt = - typeof input.amountStroops === "bigint" - ? input.amountStroops - : BigInt(input.amountStroops); + typeof input.amountStroops === "bigint" ? input.amountStroops : BigInt(input.amountStroops); const operation = this.buildCreateEscrowTx( input.invoiceId, input.sellerAddress, amountBigInt, input.dueDateTimestamp, - input.paymentTokenAddress, + input.paymentTokenAddress ); const amountStroopsStr = amountBigInt.toString(); diff --git a/src/services/stellar/invoice-token-contract.service.ts b/src/services/stellar/invoice-token-contract.service.ts index d29769a..3305e48 100644 --- a/src/services/stellar/invoice-token-contract.service.ts +++ b/src/services/stellar/invoice-token-contract.service.ts @@ -38,7 +38,7 @@ export class InvoiceTokenContractService { constructor( dependenciesOrContractId: string | InvoiceTokenContractServiceDependencies, - logger?: AppLogger, + logger?: AppLogger ) { if (typeof dependenciesOrContractId === "string") { if (!dependenciesOrContractId) { @@ -75,11 +75,10 @@ export class InvoiceTokenContractService { */ public buildMintTx( recipientAddress: string, - tokenAmount: bigint | number | string, + tokenAmount: bigint | number | string ): xdr.Operation { const toScVal = new Address(recipientAddress).toScVal(); - const amountBigInt = - typeof tokenAmount === "bigint" ? tokenAmount : BigInt(tokenAmount); + const amountBigInt = typeof tokenAmount === "bigint" ? tokenAmount : BigInt(tokenAmount); const amountScVal = nativeToScVal(amountBigInt, { type: "i128" }); return this.contract.call("mint", toScVal, amountScVal); @@ -128,10 +127,9 @@ export class InvoiceTokenContractService { public async mintInvoiceTokens( invoiceId: string, recipientAddress: string, - tokenAmount: bigint | number | string, + tokenAmount: bigint | number | string ): Promise { - const amountBigInt = - typeof tokenAmount === "bigint" ? tokenAmount : BigInt(tokenAmount); + const amountBigInt = typeof tokenAmount === "bigint" ? tokenAmount : BigInt(tokenAmount); const operation = this.buildMintTx(recipientAddress, amountBigInt); this.logger.info("Minted invoice tokens for invoice", { diff --git a/src/services/stellar/orchestrate-investment-funding.service.ts b/src/services/stellar/orchestrate-investment-funding.service.ts index f0aa087..445528e 100644 --- a/src/services/stellar/orchestrate-investment-funding.service.ts +++ b/src/services/stellar/orchestrate-investment-funding.service.ts @@ -23,9 +23,7 @@ export interface SorobanEscrowFundingDraft { } export interface SorobanEscrowClient { - prepareInvestmentFunding( - input: SorobanEscrowFundingInput, - ): Promise; + prepareInvestmentFunding(input: SorobanEscrowFundingInput): Promise; } interface FundingUnitOfWork { @@ -78,17 +76,13 @@ const NOOP_LOGGER: AppLogger = { export class OrchestrateInvestmentFundingService { private readonly logger: AppLogger; - constructor( - private readonly dependencies: OrchestrateInvestmentFundingServiceDependencies, - ) { + constructor(private readonly dependencies: OrchestrateInvestmentFundingServiceDependencies) { this.logger = (dependencies.logger ?? NOOP_LOGGER).child({ component: "soroban-escrow-funding", }); } - async orchestrateFunding( - investmentId: string, - ): Promise { + async orchestrateFunding(investmentId: string): Promise { const investment = await this.dependencies.investmentReader.findById(investmentId); if (!investment) { @@ -99,7 +93,7 @@ export class OrchestrateInvestmentFundingService { throw new ServiceError( "invalid_investment_state", "Only pending investments can be funded.", - 409, + 409 ); } @@ -107,7 +101,7 @@ export class OrchestrateInvestmentFundingService { throw new ServiceError( "invoice_not_found", "Investment must be linked to an invoice before funding.", - 409, + 409 ); } @@ -126,7 +120,7 @@ export class OrchestrateInvestmentFundingService { throw new ServiceError( "soroban_contract_not_configured", "Soroban escrow is enabled but no contract ID is configured.", - 500, + 500 ); } @@ -175,7 +169,7 @@ export class OrchestrateInvestmentFundingService { } const existingTransaction = await unitOfWork.findTransactionByInvestmentIdForUpdate( - lockedInvestment.id, + lockedInvestment.id ); const transaction = @@ -247,7 +241,7 @@ class TypeOrmFundingTransactionRunner implements FundingTransactionRunner { manager.getRepository(Transaction).save(transaction), createTransaction: (input: Partial) => manager.getRepository(Transaction).create(input), - }), + }) ); } } @@ -256,12 +250,10 @@ export function createOrchestrateInvestmentFundingService( dataSource: DataSource, sorobanEscrowClient: SorobanEscrowClient, config: OrchestrateInvestmentFundingServiceDependencies["config"], - logger?: AppLogger, + logger?: AppLogger ): OrchestrateInvestmentFundingService { return new OrchestrateInvestmentFundingService({ - investmentReader: new TypeOrmInvestmentFundingReader( - dataSource.getRepository(Investment), - ), + investmentReader: new TypeOrmInvestmentFundingReader(dataSource.getRepository(Investment)), transactionRunner: new TypeOrmFundingTransactionRunner(dataSource), sorobanEscrowClient, config, diff --git a/src/services/stellar/payment-distributor-contract.service.ts b/src/services/stellar/payment-distributor-contract.service.ts index 0da9875..107fb87 100644 --- a/src/services/stellar/payment-distributor-contract.service.ts +++ b/src/services/stellar/payment-distributor-contract.service.ts @@ -1,4 +1,13 @@ -import { Contract, Address, nativeToScVal, xdr, SorobanRpc, Keypair, TransactionBuilder, BASE_FEE } from "stellar-sdk"; +import { + Contract, + Address, + nativeToScVal, + xdr, + SorobanRpc, + Keypair, + TransactionBuilder, + BASE_FEE, +} from "stellar-sdk"; import type { AppLogger } from "../../observability/logger"; import { logger as globalLogger } from "../../observability/logger"; @@ -31,7 +40,10 @@ export interface DistributePayoutsInput { feeBps: number; } -export interface DistributePayoutsResult { transactionHash: string; ledger: number | null; } +export interface DistributePayoutsResult { + transactionHash: string; + ledger: number | null; +} const MAX_FEE_BPS = 10_000; @@ -59,7 +71,7 @@ export class PaymentDistributorContractService { constructor( dependenciesOrContractId: string | PaymentDistributorContractServiceDependencies, - logger?: AppLogger, + logger?: AppLogger ) { if (typeof dependenciesOrContractId === "string") { if (!dependenciesOrContractId) { @@ -108,7 +120,7 @@ export class PaymentDistributorContractService { invoiceId: string, recipients: PayoutRecipient[], platformFeeAccount: string, - feeBps: number, + feeBps: number ): xdr.Operation { if (recipients.length === 0) { throw new Error("At least one payout recipient is required."); @@ -118,7 +130,7 @@ export class PaymentDistributorContractService { } const recipientAddressesScVal = xdr.ScVal.scvVec( - recipients.map((recipient) => new Address(recipient.address).toScVal()), + recipients.map((recipient) => new Address(recipient.address).toScVal()) ); const recipientAmountsScVal = xdr.ScVal.scvVec( @@ -128,7 +140,7 @@ export class PaymentDistributorContractService { ? recipient.amountStroops : BigInt(recipient.amountStroops); return nativeToScVal(amountBigInt, { type: "i128" }); - }), + }) ); return this.contract.call( @@ -137,7 +149,7 @@ export class PaymentDistributorContractService { recipientAddressesScVal, recipientAmountsScVal, new Address(platformFeeAccount).toScVal(), - nativeToScVal(feeBps, { type: "u32" }), + nativeToScVal(feeBps, { type: "u32" }) ); } @@ -148,7 +160,10 @@ export class PaymentDistributorContractService { if (this.verifyDistributorWiring && !(await this.verifyDistributorWiring())) { throw new Error("Payment distributor is not initialized on the invoice escrow contract."); } - const recipientTotal = input.recipients.reduce((sum, recipient) => sum + BigInt(recipient.amountStroops), 0n); + const recipientTotal = input.recipients.reduce( + (sum, recipient) => sum + BigInt(recipient.amountStroops), + 0n + ); const fee = (input.totalAmountStroops * BigInt(input.feeBps)) / 10_000n; if (recipientTotal + fee > input.totalAmountStroops) { throw new Error("Payout recipients and protocol fee exceed the settlement total."); @@ -159,19 +174,37 @@ export class PaymentDistributorContractService { const transaction = new TransactionBuilder(account, { fee: BASE_FEE, networkPassphrase: this.networkPassphrase, - }).addOperation(this.buildDistributePayoutsTx(input.invoiceId, input.recipients, input.feeRecipient, input.feeBps)).setTimeout(30).build(); + }) + .addOperation( + this.buildDistributePayoutsTx( + input.invoiceId, + input.recipients, + input.feeRecipient, + input.feeBps + ) + ) + .setTimeout(30) + .build(); const prepared = await this.rpcServer.prepareTransaction(transaction); prepared.sign(signer); const submitted = await this.rpcServer.sendTransaction(prepared); - if (submitted.status === "ERROR") throw new Error("Payment distribution transaction was rejected by Soroban RPC."); + if (submitted.status === "ERROR") + throw new Error("Payment distribution transaction was rejected by Soroban RPC."); for (let attempt = 0; attempt < this.confirmationAttempts; attempt++) { const result = await this.rpcServer.getTransaction(submitted.hash); if (result.status === "SUCCESS") { - this.logger.info("Payment distribution confirmed on-chain.", { invoice_id: input.invoiceId, transaction_hash: submitted.hash }); - return { transactionHash: submitted.hash, ledger: "ledger" in result ? Number(result.ledger) : null }; + this.logger.info("Payment distribution confirmed on-chain.", { + invoice_id: input.invoiceId, + transaction_hash: submitted.hash, + }); + return { + transactionHash: submitted.hash, + ledger: "ledger" in result ? Number(result.ledger) : null, + }; } - if (result.status === "FAILED") throw new Error("Payment distribution transaction reverted on-chain."); + if (result.status === "FAILED") + throw new Error("Payment distribution transaction reverted on-chain."); await new Promise((resolve) => setTimeout(resolve, this.confirmationPollMs)); } throw new Error("Timed out waiting for payment distribution confirmation."); diff --git a/src/services/stellar/reconciliation-retry.ts b/src/services/stellar/reconciliation-retry.ts index 7065c44..6a40eb5 100644 --- a/src/services/stellar/reconciliation-retry.ts +++ b/src/services/stellar/reconciliation-retry.ts @@ -10,9 +10,7 @@ import { RetryableHorizonError } from "./verify-payment.service"; * authorization issues, business-rule violations) are not retryable because no * amount of retrying will change the outcome. */ -export type ReconciliationFailureKind = - | "transient_provider" - | "permanent_validation"; +export type ReconciliationFailureKind = "transient_provider" | "permanent_validation"; export interface ReconciliationRetryDecision { /** `true` when the failure is safe to retry on a later tick. */ @@ -62,7 +60,7 @@ function timeoutDecision(attempt: number, name: string): ReconciliationRetryDeci */ export function classifyReconciliationError( error: unknown, - attempt = 1, + attempt = 1 ): ReconciliationRetryDecision { // 1. Explicit request timeouts / aborts are always transient. if (error instanceof Error && TIMEOUT_ERROR_NAMES.has(error.name)) { diff --git a/src/services/stellar/verify-payment.service.ts b/src/services/stellar/verify-payment.service.ts index 0e611ae..6993097 100644 --- a/src/services/stellar/verify-payment.service.ts +++ b/src/services/stellar/verify-payment.service.ts @@ -65,7 +65,7 @@ interface PaymentVerificationUnitOfWork { interface PaymentTransactionRunner { runInTransaction( - callback: (unitOfWork: PaymentVerificationUnitOfWork) => Promise, + callback: (unitOfWork: PaymentVerificationUnitOfWork) => Promise ): Promise; } @@ -89,12 +89,11 @@ export class VerifyPaymentService { this.transactionRunner = dependencies.transactionRunner; this.config = dependencies.config; this.fetchImplementation = dependencies.fetchImplementation ?? fetch; - this.sleep = dependencies.sleep ?? ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms))); + this.sleep = + dependencies.sleep ?? ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms))); } - async verifyPayment( - input: PaymentVerificationInput, - ): Promise { + async verifyPayment(input: PaymentVerificationInput): Promise { const investment = await this.investmentReader.findById(input.investmentId); if (!investment) { @@ -104,7 +103,8 @@ export class VerifyPaymentService { if (investment.status === InvestmentStatus.CONFIRMED) { if ( investment.transactionHash === input.stellarTxHash && - investment.stellarOperationIndex === (input.operationIndex ?? investment.stellarOperationIndex) + investment.stellarOperationIndex === + (input.operationIndex ?? investment.stellarOperationIndex) ) { return { outcome: "already_verified", @@ -119,14 +119,14 @@ export class VerifyPaymentService { throw new ServiceError( "reconciliation_conflict", "Investment is already confirmed with a different Stellar payment.", - 409, + 409 ); } const matchedPayment = await this.fetchAndValidatePayment( input.stellarTxHash, investment.investmentAmount, - input.operationIndex, + input.operationIndex ); return this.transactionRunner.runInTransaction(async (unitOfWork) => { @@ -137,14 +137,14 @@ export class VerifyPaymentService { } const linkedTransactions = await unitOfWork.findTransactionsByInvestmentIdForUpdate( - lockedInvestment.id, + lockedInvestment.id ); if (linkedTransactions.length > 1) { throw new ServiceError( "reconciliation_conflict", "Multiple transaction rows are linked to the same investment.", - 409, + 409 ); } @@ -168,7 +168,7 @@ export class VerifyPaymentService { throw new ServiceError( "reconciliation_conflict", "Investment was confirmed by another transaction while verification was in progress.", - 409, + 409 ); } @@ -182,7 +182,7 @@ export class VerifyPaymentService { throw new ServiceError( "reconciliation_conflict", "Transaction row is already linked to a different Stellar hash.", - 409, + 409 ); } @@ -230,22 +230,18 @@ export class VerifyPaymentService { private async fetchAndValidatePayment( stellarTxHash: string, expectedAmount: string, - operationIndex?: number, + operationIndex?: number ): Promise { - const transaction = normalizeHorizonTransaction(await this.fetchJson( - `/transactions/${stellarTxHash}`, - )); + const transaction = normalizeHorizonTransaction( + await this.fetchJson(`/transactions/${stellarTxHash}`) + ); if (!transaction.successful) { - throw new ServiceError( - "invalid_payment", - "The Stellar transaction was not successful.", - 422, - ); + throw new ServiceError("invalid_payment", "The Stellar transaction was not successful.", 422); } const operations = await this.fetchJson( - `/transactions/${stellarTxHash}/operations?limit=200&order=asc`, + `/transactions/${stellarTxHash}/operations?limit=200&order=asc` ); const paymentOperations = (operations._embedded?.records ?? []) @@ -265,11 +261,7 @@ export class VerifyPaymentService { operation.assetIssuer === this.config.usdcAssetIssuer && operation.destination === this.config.escrowPublicKey && operation.amount !== null && - amountsWithinDelta( - operation.amount, - expectedAmount, - this.config.allowedAmountDelta, - ) + amountsWithinDelta(operation.amount, expectedAmount, this.config.allowedAmountDelta) ); }); @@ -277,7 +269,7 @@ export class VerifyPaymentService { throw new ServiceError( "invalid_payment", "No Stellar payment operation matched the expected asset, amount, and destination.", - 422, + 422 ); } @@ -285,7 +277,7 @@ export class VerifyPaymentService { throw new ServiceError( "invalid_payment", "Multiple payment operations matched. Supply operationIndex to disambiguate.", - 422, + 422 ); } @@ -316,7 +308,7 @@ export class VerifyPaymentService { throw new ServiceError( "transaction_not_found", "The Stellar transaction could not be found in Horizon.", - 404, + 404 ); } @@ -328,7 +320,7 @@ export class VerifyPaymentService { throw new ServiceError( "horizon_request_failed", "Horizon rejected the verification request.", - 502, + 502 ); } @@ -342,7 +334,7 @@ export class VerifyPaymentService { throw new ServiceError( "horizon_unavailable", "Horizon is temporarily unavailable. Please retry later.", - 503, + 503 ); } @@ -353,7 +345,7 @@ export class VerifyPaymentService { throw new ServiceError( "horizon_unavailable", "Horizon is temporarily unavailable. Please retry later.", - 503, + 503 ); } } @@ -372,7 +364,7 @@ class TypeOrmTransactionRunner implements PaymentTransactionRunner { constructor(private readonly dataSource: DataSource) {} runInTransaction( - callback: (unitOfWork: PaymentVerificationUnitOfWork) => Promise, + callback: (unitOfWork: PaymentVerificationUnitOfWork) => Promise ): Promise { return this.dataSource.transaction(async (manager) => callback({ @@ -390,14 +382,14 @@ class TypeOrmTransactionRunner implements PaymentTransactionRunner { manager.getRepository(Transaction).save(transaction), createTransaction: (input: Partial) => manager.getRepository(Transaction).create(input), - }), + }) ); } } export function createVerifyPaymentService( dataSource: DataSource, - config: PaymentVerificationConfig, + config: PaymentVerificationConfig ): VerifyPaymentService { return new VerifyPaymentService({ investmentReader: new TypeOrmInvestmentReader(dataSource.getRepository(Investment)), @@ -418,9 +410,8 @@ function amountsWithinDelta(actual: string, expected: string, delta: string): bo const expectedValue = toScaledBigInt(expected, scale); const deltaValue = toScaledBigInt(delta, scale); - const difference = actualValue >= expectedValue - ? actualValue - expectedValue - : expectedValue - actualValue; + const difference = + actualValue >= expectedValue ? actualValue - expectedValue : expectedValue - actualValue; return difference <= deltaValue; } diff --git a/src/services/webhook-dispatcher.service.ts b/src/services/webhook-dispatcher.service.ts index 98f93b9..7aa7400 100644 --- a/src/services/webhook-dispatcher.service.ts +++ b/src/services/webhook-dispatcher.service.ts @@ -24,25 +24,23 @@ export interface WebhookDispatchResult { export class WebhookDispatcherService { constructor( private readonly dataSource: DataSource, - private readonly appLogger: AppLogger = logger, + private readonly appLogger: AppLogger = logger ) {} async dispatchWebhookEvent( eventType: string, payload: unknown, - eventId?: string, + eventId?: string ): Promise { const subscriptions = await this.dataSource .getRepository(WebhookSubscription) .find({ where: { active: true } }); const body = JSON.stringify({ eventType, payload }); const eligible = subscriptions.filter((subscription) => - subscription.eventTypes.includes(eventType), + subscription.eventTypes.includes(eventType) ); return Promise.all( - eligible.map((subscription) => - this.deliver(subscription, eventType, body, eventId), - ), + eligible.map((subscription) => this.deliver(subscription, eventType, body, eventId)) ); } @@ -50,7 +48,7 @@ export class WebhookDispatcherService { subscription: WebhookSubscription, eventType: string, body: string, - eventId?: string, + eventId?: string ): Promise { // Idempotency: a duplicate event (same subscription + eventId) that has // already been delivered successfully must not be re-delivered, otherwise @@ -97,7 +95,7 @@ export class WebhookDispatcherService { attempt, response.status, delivered, - delivered ? null : `HTTP ${response.status}`, + delivered ? null : `HTTP ${response.status}` ); if (delivered) { return { @@ -118,7 +116,7 @@ export class WebhookDispatcherService { attempt, lastStatus, false, - lastError, + lastError ); } if (attempt < 3) { @@ -141,10 +139,7 @@ export class WebhookDispatcherService { }; } - private async alreadyDelivered( - subscriptionId: string, - eventId: string, - ): Promise { + private async alreadyDelivered(subscriptionId: string, eventId: string): Promise { const existing = await this.dataSource .getRepository(WebhookDeliveryLog) .findOne({ where: { subscriptionId, eventId, delivered: true } }); @@ -158,7 +153,7 @@ export class WebhookDispatcherService { attempt: number, responseStatus: number | null, delivered: boolean, - errorMessage: string | null, + errorMessage: string | null ): Promise { await this.dataSource.getRepository(WebhookDeliveryLog).save({ subscriptionId, @@ -182,7 +177,7 @@ export class WebhookDispatcherService { export function createWebhookDispatcherService( dataSource: DataSource, - appLogger?: AppLogger, + appLogger?: AppLogger ): WebhookDispatcherService { return new WebhookDispatcherService(dataSource, appLogger); } diff --git a/src/utils/cursor-pagination.utils.ts b/src/utils/cursor-pagination.utils.ts index 0bc9b00..a6e98d6 100644 --- a/src/utils/cursor-pagination.utils.ts +++ b/src/utils/cursor-pagination.utils.ts @@ -11,7 +11,7 @@ * @returns A base64-encoded cursor string */ export function encodeCursor(date: Date, id: string): string { - return Buffer.from(`${date.toISOString()}::${id}`).toString("base64"); + return Buffer.from(`${date.toISOString()}::${id}`).toString("base64"); } /** @@ -22,25 +22,25 @@ export function encodeCursor(date: Date, id: string): string { * @throws If the cursor format is invalid */ export function decodeCursor(cursor: string): { createdAt: Date; id: string } { - const decoded = Buffer.from(cursor, "base64").toString("utf-8"); - const separatorIndex = decoded.indexOf("::"); + const decoded = Buffer.from(cursor, "base64").toString("utf-8"); + const separatorIndex = decoded.indexOf("::"); - if (separatorIndex === -1) { - throw new Error("Invalid cursor format: expected 'ISO_DATE::ID'"); - } + if (separatorIndex === -1) { + throw new Error("Invalid cursor format: expected 'ISO_DATE::ID'"); + } - const createdAtIso = decoded.slice(0, separatorIndex); - const id = decoded.slice(separatorIndex + 2); + const createdAtIso = decoded.slice(0, separatorIndex); + const id = decoded.slice(separatorIndex + 2); - if (!createdAtIso || !id) { - throw new Error("Invalid cursor format: missing date or id component"); - } + if (!createdAtIso || !id) { + throw new Error("Invalid cursor format: missing date or id component"); + } - const createdAt = new Date(createdAtIso); + const createdAt = new Date(createdAtIso); - if (isNaN(createdAt.getTime())) { - throw new Error("Invalid cursor format: unable to parse date"); - } + if (isNaN(createdAt.getTime())) { + throw new Error("Invalid cursor format: unable to parse date"); + } - return { createdAt, id }; + return { createdAt, id }; } diff --git a/src/utils/discount-calculator.utils.ts b/src/utils/discount-calculator.utils.ts index 74364c4..c2ed8c2 100644 --- a/src/utils/discount-calculator.utils.ts +++ b/src/utils/discount-calculator.utils.ts @@ -25,7 +25,7 @@ export interface InvoiceTermsResult { */ export function calculateTenureDays( dueDateInput: Date | string, - referenceDateInput?: Date | string, + referenceDateInput?: Date | string ): number { const due = typeof dueDateInput === "string" ? new Date(dueDateInput) : dueDateInput; const ref = referenceDateInput @@ -50,7 +50,13 @@ export function calculateTenureDays( * Pure calculation utility for invoice discounting terms, fees, net advance amount, and annualized APR. */ export function calculateInvoiceTerms(input: InvoiceTermsInput): InvoiceTermsResult { - const { faceValue: rawFaceValue, dueDate, discountBps, platformFeeBps = 0, referenceDate } = input; + const { + faceValue: rawFaceValue, + dueDate, + discountBps, + platformFeeBps = 0, + referenceDate, + } = input; const faceValue = new Decimal(rawFaceValue); if (faceValue.isNegative() || faceValue.isZero()) { @@ -78,11 +84,7 @@ export function calculateInvoiceTerms(input: InvoiceTermsInput): InvoiceTermsRes // APR = (discountAmount / advanceAmount) * (365 / tenureDays) * 100 let apr = new Decimal(0); if (advanceAmount.gt(0) && discountAmount.gt(0) && tenureDays > 0) { - apr = discountAmount - .dividedBy(advanceAmount) - .times(365) - .dividedBy(tenureDays) - .times(100); + apr = discountAmount.dividedBy(advanceAmount).times(365).dividedBy(tenureDays).times(100); } return { diff --git a/src/utils/fee-calculator.utils.ts b/src/utils/fee-calculator.utils.ts index 0187266..11879f6 100644 --- a/src/utils/fee-calculator.utils.ts +++ b/src/utils/fee-calculator.utils.ts @@ -3,10 +3,7 @@ import Decimal from "decimal.js"; const BASIS_POINTS_DIVISOR = new Decimal(10_000); const MONEY_DECIMAL_PLACES = 2; -export function calculatePlatformFee( - amount: Decimal, - feeBps: number, -): Decimal { +export function calculatePlatformFee(amount: Decimal, feeBps: number): Decimal { return amount .mul(feeBps) .div(BASIS_POINTS_DIVISOR) diff --git a/src/utils/horizon-response.ts b/src/utils/horizon-response.ts index b01b386..d3d37f7 100644 --- a/src/utils/horizon-response.ts +++ b/src/utils/horizon-response.ts @@ -30,7 +30,11 @@ function optionalString(value: unknown): string | null { } export function normalizeHorizonTransaction(value: unknown): NormalizedHorizonTransaction { - if (typeof value !== "object" || value === null || typeof (value as { successful?: unknown }).successful !== "boolean") { + if ( + typeof value !== "object" || + value === null || + typeof (value as { successful?: unknown }).successful !== "boolean" + ) { throw new HorizonValidationError("Horizon transaction is missing required successful field"); } const transaction = value as Record; @@ -47,8 +51,14 @@ export function normalizeHorizonPayment(value: unknown): NormalizedHorizonPaymen throw new HorizonValidationError("Horizon payment must be an object"); } const payment = value as Record; - if (typeof payment.type !== "string" || typeof payment.amount !== "string" || typeof payment.to !== "string") { - throw new HorizonValidationError("Horizon payment is missing required type, amount, or destination"); + if ( + typeof payment.type !== "string" || + typeof payment.amount !== "string" || + typeof payment.to !== "string" + ) { + throw new HorizonValidationError( + "Horizon payment is missing required type, amount, or destination" + ); } return { id: optionalString(payment.id), diff --git a/src/utils/http-error.ts b/src/utils/http-error.ts index cbd55ee..82bd59a 100644 --- a/src/utils/http-error.ts +++ b/src/utils/http-error.ts @@ -16,7 +16,6 @@ export interface ApiResponseEnvelope { }; } - // ---------------- APP ERROR ---------------- export class AppError extends Error { @@ -24,12 +23,7 @@ export class AppError extends Error { code: string; details?: unknown; - constructor( - statusCode: number, - message: string, - code: string, - details?: unknown - ) { + constructor(statusCode: number, message: string, code: string, details?: unknown) { super(message); this.name = "AppError"; this.statusCode = statusCode; @@ -38,7 +32,6 @@ export class AppError extends Error { } } - // ---------------- HTTP ERROR ---------------- export class HttpError extends Error { @@ -46,15 +39,11 @@ export class HttpError extends Error { code: string; details?: unknown; - constructor( - statusCode: number, - message: string, - details?: unknown - ) { + constructor(statusCode: number, message: string, details?: unknown) { super(message); this.name = "HttpError"; this.statusCode = statusCode; this.code = `HTTP_${statusCode}`; this.details = details; } -} \ No newline at end of file +} diff --git a/src/utils/invoice-state.utils.ts b/src/utils/invoice-state.utils.ts index 5997004..0a0c3c3 100644 --- a/src/utils/invoice-state.utils.ts +++ b/src/utils/invoice-state.utils.ts @@ -6,7 +6,11 @@ export function isValidInvoiceStateTransition( ): boolean { const validTransitions: Record = { [InvoiceStatus.DRAFT]: [InvoiceStatus.PUBLISHED, InvoiceStatus.CANCELLED], - [InvoiceStatus.PENDING]: [InvoiceStatus.PUBLISHED, InvoiceStatus.CANCELLED, InvoiceStatus.REJECTED], + [InvoiceStatus.PENDING]: [ + InvoiceStatus.PUBLISHED, + InvoiceStatus.CANCELLED, + InvoiceStatus.REJECTED, + ], [InvoiceStatus.PUBLISHED]: [InvoiceStatus.FUNDED, InvoiceStatus.CANCELLED], [InvoiceStatus.FUNDED]: [InvoiceStatus.SETTLED, InvoiceStatus.CANCELLED], [InvoiceStatus.SETTLED]: [InvoiceStatus.CANCELLED], diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts index d82f93c..2ff56e6 100644 --- a/src/utils/pagination.ts +++ b/src/utils/pagination.ts @@ -42,11 +42,11 @@ export async function queryInvoicesPage( if (filters.status) { if (Array.isArray(filters.status)) { - if (filters.status.length > 0) { - queryBuilder.andWhere("invoice.status IN (:...statuses)", { statuses: filters.status }); - } + if (filters.status.length > 0) { + queryBuilder.andWhere("invoice.status IN (:...statuses)", { statuses: filters.status }); + } } else { - queryBuilder.andWhere("invoice.status = :status", { status: filters.status }); + queryBuilder.andWhere("invoice.status = :status", { status: filters.status }); } } @@ -83,12 +83,14 @@ export async function queryInvoicesPage( let nextCursor: string | null = null; if (items.length > 0) { const lastItem = items[items.length - 1]; - nextCursor = Buffer.from(`${lastItem.createdAt.toISOString()}|${lastItem.id}`).toString("base64"); + nextCursor = Buffer.from(`${lastItem.createdAt.toISOString()}|${lastItem.id}`).toString( + "base64" + ); } return { data: items, has_more: hasMore, - next_cursor: nextCursor + next_cursor: nextCursor, }; } diff --git a/src/utils/query-pagination.utils.ts b/src/utils/query-pagination.utils.ts index 472ec7e..792b1b9 100644 --- a/src/utils/query-pagination.utils.ts +++ b/src/utils/query-pagination.utils.ts @@ -67,11 +67,11 @@ function invalidCursor(message: string): ServiceError { export function encodeQueryCursor( field: string, value: string | number | Date, - id?: string, + id?: string ): string { const normalizedValue = value instanceof Date ? value.toISOString() : value; return Buffer.from( - JSON.stringify({ field, value: normalizedValue, ...(id !== undefined ? { id } : {}) }), + JSON.stringify({ field, value: normalizedValue, ...(id !== undefined ? { id } : {}) }) ).toString("base64"); } @@ -125,7 +125,7 @@ function splitCursorField(cursorField: string): { alias: string; column: string const parts = cursorField.split("."); if (parts.length !== 2 || !parts[0] || !parts[1]) { throw invalidCursor( - `Invalid cursorField "${cursorField}": expected "." (e.g. "invoice.createdAt")`, + `Invalid cursorField "${cursorField}": expected "." (e.g. "invoice.createdAt")` ); } return { alias: parts[0], column: parts[1] }; @@ -146,7 +146,7 @@ function splitCursorField(cursorField: string): { alias: string; column: string * secondary sort, so equal primary sort values never produce gaps or repeats. */ export async function paginateQuery( - options: PaginateQueryOptions, + options: PaginateQueryOptions ): Promise> { const { queryBuilder, cursorField, limit, cursor } = options; const order = options.order ?? "DESC"; @@ -164,7 +164,7 @@ export async function paginateQuery( const decoded = decodeQueryCursor(cursor); if (decoded.field !== cursorField) { throw invalidCursor( - `Invalid cursor: was encoded for field "${decoded.field}" but query is paginating on "${cursorField}"`, + `Invalid cursor: was encoded for field "${decoded.field}" but query is paginating on "${cursorField}"` ); } @@ -183,7 +183,7 @@ export async function paginateQuery( { [paramName]: decoded.value, [tiebreakerParamName]: decoded.id, - }, + } ); } } @@ -204,16 +204,20 @@ export async function paginateQuery( if (hasMore && items.length > 0) { const lastItem = items[items.length - 1] as unknown as Record; const lastValue = lastItem[columnOf(cursorField)]; - if (typeof lastValue === "string" || typeof lastValue === "number" || lastValue instanceof Date) { + if ( + typeof lastValue === "string" || + typeof lastValue === "number" || + lastValue instanceof Date + ) { const lastId = lastItem[idColumn]; nextCursor = encodeQueryCursor( cursorField, lastValue, - typeof lastId === "string" ? lastId : undefined, + typeof lastId === "string" ? lastId : undefined ); } else { throw invalidCursor( - `paginateQuery: cursor column "${columnOf(cursorField)}" must resolve to a string, number, or Date (got ${typeof lastValue})`, + `paginateQuery: cursor column "${columnOf(cursorField)}" must resolve to a string, number, or Date (got ${typeof lastValue})` ); } } diff --git a/src/utils/response-envelope.utils.ts b/src/utils/response-envelope.utils.ts index 89004ea..f9d3c9d 100644 --- a/src/utils/response-envelope.utils.ts +++ b/src/utils/response-envelope.utils.ts @@ -8,28 +8,28 @@ * @returns A paginated response envelope object */ export function buildPaginatedResponse( - items: T[], - totalCount: number, - limit: number, - nextCursor?: string, + items: T[], + totalCount: number, + limit: number, + nextCursor?: string ): { - success: true; - data: T[]; - meta: { - total: number; - limit: number; - hasNextPage: boolean; - nextCursor: string | null; - }; + success: true; + data: T[]; + meta: { + total: number; + limit: number; + hasNextPage: boolean; + nextCursor: string | null; + }; } { - return { - success: true, - data: items, - meta: { - total: totalCount, - limit, - hasNextPage: Boolean(nextCursor), - nextCursor: nextCursor || null, - }, - }; -} \ No newline at end of file + return { + success: true, + data: items, + meta: { + total: totalCount, + limit, + hasNextPage: Boolean(nextCursor), + nextCursor: nextCursor || null, + }, + }; +} diff --git a/src/utils/stellar-challenge.ts b/src/utils/stellar-challenge.ts index 26338a3..d04d400 100644 --- a/src/utils/stellar-challenge.ts +++ b/src/utils/stellar-challenge.ts @@ -18,7 +18,7 @@ export interface WalletChallenge { export function buildWalletChallenge( walletAddress: string, networkPassphrase: string, - serverKeypair: Keypair, + serverKeypair: Keypair ): WalletChallenge { if (!StrKey.isValidEd25519PublicKey(walletAddress)) { throw new HttpError(400, "Invalid wallet address."); @@ -36,7 +36,7 @@ export function buildWalletChallenge( name: "web_auth_domain", value: Buffer.from(nonce, "utf8"), source: walletAddress, - }), + }) ) .setTimeout(300) .build(); diff --git a/src/utils/webhook-signature.ts b/src/utils/webhook-signature.ts index 214f428..d4802be 100644 --- a/src/utils/webhook-signature.ts +++ b/src/utils/webhook-signature.ts @@ -19,7 +19,7 @@ export function computeWebhookSignature(payload: string, secret: string): string export function verifyWebhookSignature( payload: string, signature: string, - secret: string, + secret: string ): boolean { try { if (!payload || !signature || !secret) { @@ -57,7 +57,7 @@ export type WebhookSignatureErrorCode = export class WebhookSignatureError extends Error { constructor( public readonly code: WebhookSignatureErrorCode, - message: string, + message: string ) { super(message); this.name = "WebhookSignatureError"; @@ -77,7 +77,7 @@ export const DEFAULT_MAX_TIMESTAMP_SKEW_MS = 5 * 60 * 1000; export function computeWebhookSignatureForTimestamp( payload: string, timestamp: string, - secret: string, + secret: string ): string { return computeWebhookSignature(`${timestamp}.${payload}`, secret); } @@ -112,9 +112,7 @@ export interface VerifyWebhookHeadersOptions { * failure. Never returns `false` — every rejection is a typed error that a * handler can map to a 4xx response. */ -export function verifyWebhookSignatureHeaders( - options: VerifyWebhookHeadersOptions, -): string { +export function verifyWebhookSignatureHeaders(options: VerifyWebhookHeadersOptions): string { const { payload, signature, @@ -125,23 +123,20 @@ export function verifyWebhookSignatureHeaders( } = options; if (!secret) { - throw new WebhookSignatureError( - "INVALID_SIGNATURE", - "Webhook secret is not configured.", - ); + throw new WebhookSignatureError("INVALID_SIGNATURE", "Webhook secret is not configured."); } if (timestamp === undefined || timestamp === null || timestamp === "") { throw new WebhookSignatureError( "MISSING_TIMESTAMP", - `Missing '${WEBHOOK_TIMESTAMP_HEADER}' header.`, + `Missing '${WEBHOOK_TIMESTAMP_HEADER}' header.` ); } if (signature === undefined || signature === null || signature === "") { throw new WebhookSignatureError( "MISSING_SIGNATURE", - `Missing '${WEBHOOK_SIGNATURE_HEADER}' header.`, + `Missing '${WEBHOOK_SIGNATURE_HEADER}' header.` ); } @@ -150,14 +145,14 @@ export function verifyWebhookSignatureHeaders( if (Number.isNaN(skewMs) || !Number.isFinite(skewMs)) { throw new WebhookSignatureError( "TIMESTAMP_OUT_OF_RANGE", - `'${WEBHOOK_TIMESTAMP_HEADER}' is not a valid timestamp.`, + `'${WEBHOOK_TIMESTAMP_HEADER}' is not a valid timestamp.` ); } if (Math.abs(skewMs) > maxTimestampSkewMs) { throw new WebhookSignatureError( "TIMESTAMP_SKEWED", - `'${WEBHOOK_TIMESTAMP_HEADER}' is outside the allowed ${maxTimestampSkewMs}ms window.`, + `'${WEBHOOK_TIMESTAMP_HEADER}' is outside the allowed ${maxTimestampSkewMs}ms window.` ); } @@ -165,7 +160,7 @@ export function verifyWebhookSignatureHeaders( if (!/^[0-9a-f]{64}$/i.test(signature)) { throw new WebhookSignatureError( "MALFORMED_SIGNATURE", - "'x-webhook-signature' is not a valid HMAC-SHA256 hex signature.", + "'x-webhook-signature' is not a valid HMAC-SHA256 hex signature." ); } @@ -174,20 +169,14 @@ export function verifyWebhookSignatureHeaders( if (expected.length !== signature.length) { throw new WebhookSignatureError( "MALFORMED_SIGNATURE", - "'x-webhook-signature' has an invalid length.", + "'x-webhook-signature' has an invalid length." ); } - const matches = crypto.timingSafeEqual( - Buffer.from(expected), - Buffer.from(signature), - ); + const matches = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature)); if (!matches) { - throw new WebhookSignatureError( - "INVALID_SIGNATURE", - "Webhook signature verification failed.", - ); + throw new WebhookSignatureError("INVALID_SIGNATURE", "Webhook signature verification failed."); } return timestamp; diff --git a/src/workers/reconcile-pending-stellar-state.worker.ts b/src/workers/reconcile-pending-stellar-state.worker.ts index c648ac8..b19b780 100644 --- a/src/workers/reconcile-pending-stellar-state.worker.ts +++ b/src/workers/reconcile-pending-stellar-state.worker.ts @@ -90,8 +90,7 @@ export class ReconcilePendingStellarStateWorker { }); this.now = dependencies.now ?? (() => new Date()); this.yieldControl = - dependencies.yieldControl ?? - (() => new Promise((resolve) => setImmediate(resolve))); + dependencies.yieldControl ?? (() => new Promise((resolve) => setImmediate(resolve))); this.setIntervalFn = dependencies.setIntervalFn ?? setInterval; this.clearIntervalFn = dependencies.clearIntervalFn ?? clearInterval; } @@ -134,10 +133,7 @@ export class ReconcilePendingStellarStateWorker { const deadline = startedAt.getTime() + this.config.maxRuntimeMs; try { - const candidates = await this.repository.findPendingCandidates( - cutoff, - this.config.batchSize, - ); + const candidates = await this.repository.findPendingCandidates(cutoff, this.config.batchSize); this.attemptTracker.clear(); @@ -259,12 +255,10 @@ export class ReconcilePendingStellarStateWorker { } } -class TypeOrmReconciliationCandidateRepository - implements ReconciliationCandidateRepository -{ +class TypeOrmReconciliationCandidateRepository implements ReconciliationCandidateRepository { constructor( private readonly investmentRepository: Repository, - private readonly transactionRepository: Repository, + private readonly transactionRepository: Repository ) {} async findPendingCandidates(olderThan: Date, limit: number): Promise { @@ -337,12 +331,12 @@ export function createReconcilePendingStellarStateWorker( dataSource: DataSource, paymentVerifier: VerifyPaymentService, config: AppConfig["reconciliation"], - logger: AppLogger, + logger: AppLogger ): ReconcilePendingStellarStateWorker { return new ReconcilePendingStellarStateWorker({ repository: new TypeOrmReconciliationCandidateRepository( dataSource.getRepository(Investment), - dataSource.getRepository(Transaction), + dataSource.getRepository(Transaction) ), paymentVerifier, config, diff --git a/tests/api-envelope.test.ts b/tests/api-envelope.test.ts index 0c03b9f..1c06c4b 100644 --- a/tests/api-envelope.test.ts +++ b/tests/api-envelope.test.ts @@ -79,7 +79,7 @@ describe("Response envelope", () => { // Add a route that throws an error before the error middleware is applied // We use the router pattern to ensure the route is matched before notFoundMiddleware const router = request.agent(app); - + // Simulate an internal error by accessing a route that will throw // Since we can't add routes after app creation, we'll test via the auth routes // which will throw an error from the stub service diff --git a/tests/app-hardening.test.ts b/tests/app-hardening.test.ts index fa3cab6..3d000de 100644 --- a/tests/app-hardening.test.ts +++ b/tests/app-hardening.test.ts @@ -52,7 +52,7 @@ describe("App hardening", () => { expect(app.get("trust proxy")).toBe(1); expect(response.headers["access-control-allow-origin"]).toBe( - "https://app.stellarstate.example", + "https://app.stellarstate.example" ); }); diff --git a/tests/auth-jwt-log.test.ts b/tests/auth-jwt-log.test.ts index 11a6267..e5dc141 100644 --- a/tests/auth-jwt-log.test.ts +++ b/tests/auth-jwt-log.test.ts @@ -34,9 +34,47 @@ class InMemoryUserRepository implements UserRepositoryContract { } async findByStellarAddress(stellarAddress: string) { - return ( - [...this.users.values()].find((u) => u.stellarAddress === stellarAddress) ?? null + return [...this.users.values()].find((u) => u.stellarAddress === stellarAddress) ?? null; + } + + async findByEmail(email: string) { + return [...this.users.values()].find((u) => u.email === email) ?? null; + } + + async findAll(options?: { + skip?: number; + take?: number; + cursor?: string; + order?: "ASC" | "DESC"; + }) { + let results = [...this.users.values()].filter((u) => !u.deletedAt); + results.sort((a, b) => + options?.order === "ASC" ? a.id.localeCompare(b.id) : b.id.localeCompare(a.id) ); + if (options?.cursor) { + const cursorIndex = results.findIndex((u) => u.id === options.cursor); + if (cursorIndex >= 0) { + results = results.slice(cursorIndex + 1); + } + } + if (options?.skip) { + results = results.slice(options.skip); + } + if (options?.take) { + results = results.slice(0, options.take); + } + return results; + } + + async count(options?: { cursor?: string }): Promise { + let results = [...this.users.values()].filter((u) => !u.deletedAt); + if (options?.cursor) { + const cursorIndex = results.findIndex((u) => u.id === options.cursor); + if (cursorIndex >= 0) { + results = results.slice(0, cursorIndex); + } + } + return results.length; } async save(user: Partial) { @@ -77,7 +115,7 @@ class InMemoryChallengeRepository implements ChallengeRepositoryContract { async findByAddressAndNonceHash(stellarAddress: string, nonceHash: string) { return ( [...this.challenges.values()].find( - (c) => c.stellarAddress === stellarAddress && c.nonceHash === nonceHash, + (c) => c.stellarAddress === stellarAddress && c.nonceHash === nonceHash ) ?? null ); } @@ -88,6 +126,28 @@ class InMemoryChallengeRepository implements ChallengeRepositoryContract { challenge.consumedAt = consumedAt; return true; } + + async deleteExpired(before: Date): Promise { + let count = 0; + for (const [id, challenge] of this.challenges.entries()) { + if (challenge.expiresAt < before || (challenge.consumedAt && challenge.consumedAt < before)) { + this.challenges.delete(id); + count++; + } + } + return count; + } + + async countByStatus(status: "active" | "consumed" | "expired"): Promise { + const now = new Date(); + let count = 0; + for (const challenge of this.challenges.values()) { + if (status === "active" && !challenge.consumedAt && challenge.expiresAt > now) count++; + if (status === "consumed" && challenge.consumedAt) count++; + if (status === "expired" && !challenge.consumedAt && challenge.expiresAt <= now) count++; + } + return count; + } } // ── CaptureLogger ── @@ -143,7 +203,7 @@ function createTestServer(logger?: AppLogger) { async function completeAuthFlow( app: ReturnType, keypair: Keypair, - extraHeaders: Record = {}, + extraHeaders: Record = {} ) { const challengeRes = await request(app) .post("/api/v1/auth/challenge") @@ -171,7 +231,7 @@ describe("JWT issuance structured log (issue #111)", () => { expect(res.status).toBe(200); const jwtLog = captureLogger.entries.find( - (e) => e.level === "info" && e.message === "jwt.issued", + (e) => e.level === "info" && e.message === "jwt.issued" ); expect(jwtLog).toBeDefined(); diff --git a/tests/auth-jwt-subject-expiry.test.ts b/tests/auth-jwt-subject-expiry.test.ts index ac6a45f..9264f6b 100644 --- a/tests/auth-jwt-subject-expiry.test.ts +++ b/tests/auth-jwt-subject-expiry.test.ts @@ -3,8 +3,8 @@ import jwt from "jsonwebtoken"; import { Keypair, Networks } from "stellar-sdk"; import { AuthService } from "../src/services/auth.service"; import type { - ChallengeRepositoryContract, - UserRepositoryContract, + ChallengeRepositoryContract, + UserRepositoryContract, } from "../src/services/auth.service"; import { KYCStatus, UserType } from "../src/types/enums"; import { HttpError } from "../src/utils/http-error"; @@ -20,296 +20,355 @@ import { User } from "../src/models/User.model"; type InMemoryUser = User; interface InMemoryChallenge { - id: string; - stellarAddress: string; - nonceHash: string; - message: string; - network: string; - issuedAt: Date; - expiresAt: Date; - consumedAt: Date | null; + id: string; + stellarAddress: string; + nonceHash: string; + message: string; + network: string; + issuedAt: Date; + expiresAt: Date; + consumedAt: Date | null; } class InMemoryUserRepository implements UserRepositoryContract { - private readonly users = new Map(); - - async findById(id: string) { - return this.users.get(id) ?? null; + private readonly users = new Map(); + + async findById(id: string) { + return this.users.get(id) ?? null; + } + + async findByStellarAddress(stellarAddress: string) { + return [...this.users.values()].find((user) => user.stellarAddress === stellarAddress) ?? null; + } + + async findByEmail(email: string) { + return [...this.users.values()].find((u) => u.email === email) ?? null; + } + + async findAll(options?: { + skip?: number; + take?: number; + cursor?: string; + order?: "ASC" | "DESC"; + }) { + let results = [...this.users.values()].filter((u) => !u.deletedAt); + results.sort((a, b) => + options?.order === "ASC" ? a.id.localeCompare(b.id) : b.id.localeCompare(a.id) + ); + if (options?.cursor) { + const cursorIndex = results.findIndex((u) => u.id === options.cursor); + if (cursorIndex >= 0) { + results = results.slice(cursorIndex + 1); + } } - - async findByStellarAddress(stellarAddress: string) { - return ( - [...this.users.values()].find( - (user) => user.stellarAddress === stellarAddress, - ) ?? null - ); + if (options?.skip) { + results = results.slice(options.skip); } - - async save(user: Partial) { - const now = new Date(); - const entity: InMemoryUser = { - id: crypto.randomUUID(), - stellarAddress: user.stellarAddress ?? "", - email: user.email ?? null, - userType: user.userType ?? UserType.INVESTOR, - kycStatus: user.kycStatus ?? KYCStatus.PENDING, - createdAt: user.createdAt ?? now, - updatedAt: user.updatedAt ?? now, - deletedAt: user.deletedAt ?? null, - invoices: user.invoices ?? [], - investments: user.investments ?? [], - transactions: user.transactions ?? [], - kycVerifications: user.kycVerifications ?? [], - notifications: user.notifications ?? [], - }; - - this.users.set(entity.id, entity); - return entity; + if (options?.take) { + results = results.slice(0, options.take); + } + return results; + } + + async count(options?: { cursor?: string }): Promise { + let results = [...this.users.values()].filter((u) => !u.deletedAt); + if (options?.cursor) { + const cursorIndex = results.findIndex((u) => u.id === options.cursor); + if (cursorIndex >= 0) { + results = results.slice(0, cursorIndex); + } } + return results.length; + } + + async save(user: Partial) { + const now = new Date(); + const entity: InMemoryUser = { + id: crypto.randomUUID(), + stellarAddress: user.stellarAddress ?? "", + email: user.email ?? null, + userType: user.userType ?? UserType.INVESTOR, + kycStatus: user.kycStatus ?? KYCStatus.PENDING, + createdAt: user.createdAt ?? now, + updatedAt: user.updatedAt ?? now, + deletedAt: user.deletedAt ?? null, + invoices: user.invoices ?? [], + investments: user.investments ?? [], + transactions: user.transactions ?? [], + kycVerifications: user.kycVerifications ?? [], + notifications: user.notifications ?? [], + }; + + this.users.set(entity.id, entity); + return entity; + } } class InMemoryChallengeRepository implements ChallengeRepositoryContract { - readonly challenges = new Map(); - - async create(input: InMemoryChallenge) { - const challenge: InMemoryChallenge = { - id: crypto.randomUUID(), - stellarAddress: input.stellarAddress, - nonceHash: input.nonceHash, - message: input.message, - network: input.network, - issuedAt: input.issuedAt, - expiresAt: input.expiresAt, - consumedAt: null, - }; - - this.challenges.set(challenge.id, challenge); - return challenge; - } + readonly challenges = new Map(); + + async create(input: InMemoryChallenge) { + const challenge: InMemoryChallenge = { + id: crypto.randomUUID(), + stellarAddress: input.stellarAddress, + nonceHash: input.nonceHash, + message: input.message, + network: input.network, + issuedAt: input.issuedAt, + expiresAt: input.expiresAt, + consumedAt: null, + }; - async findByAddressAndNonceHash(stellarAddress: string, nonceHash: string) { - return ( - [...this.challenges.values()].find( - (challenge) => - challenge.stellarAddress === stellarAddress && - challenge.nonceHash === nonceHash, - ) ?? null - ); - } + this.challenges.set(challenge.id, challenge); + return challenge; + } - async consume(id: string, consumedAt: Date) { - const challenge = this.challenges.get(id); + async findByAddressAndNonceHash(stellarAddress: string, nonceHash: string) { + return ( + [...this.challenges.values()].find( + (challenge) => + challenge.stellarAddress === stellarAddress && challenge.nonceHash === nonceHash + ) ?? null + ); + } - if (!challenge || challenge.consumedAt) { - return false; - } + async consume(id: string, consumedAt: Date) { + const challenge = this.challenges.get(id); + + if (!challenge || challenge.consumedAt) { + return false; + } - challenge.consumedAt = consumedAt; - return true; + challenge.consumedAt = consumedAt; + return true; + } + + async deleteExpired(before: Date): Promise { + let count = 0; + for (const [id, challenge] of this.challenges.entries()) { + if (challenge.expiresAt < before || (challenge.consumedAt && challenge.consumedAt < before)) { + this.challenges.delete(id); + count++; + } } + return count; + } + + async countByStatus(status: "active" | "consumed" | "expired"): Promise { + const now = new Date(); + let count = 0; + for (const challenge of this.challenges.values()) { + if (status === "active" && !challenge.consumedAt && challenge.expiresAt > now) count++; + if (status === "consumed" && challenge.consumedAt) count++; + if (status === "expired" && !challenge.consumedAt && challenge.expiresAt <= now) count++; + } + return count; + } } // ── Helpers ── const TEST_SECRET = "test-secret-for-jwt-tests"; -function createAuthServiceWithTtl( - ttlString: string, - challengeTtlMs = 60_000, -): AuthService { - return new AuthService({ - userRepository: new InMemoryUserRepository(), - challengeRepository: new InMemoryChallengeRepository(), - config: { - jwt: { - secret: TEST_SECRET, - expiresIn: ttlString, - }, - auth: { - challengeTtlMs, - }, - stellar: { - network: "testnet", - networkPassphrase: Networks.TESTNET, - }, - }, - }); +function createAuthServiceWithTtl(ttlString: string, challengeTtlMs = 60_000): AuthService { + return new AuthService({ + userRepository: new InMemoryUserRepository(), + challengeRepository: new InMemoryChallengeRepository(), + config: { + jwt: { + secret: TEST_SECRET, + expiresIn: ttlString, + }, + auth: { + challengeTtlMs, + }, + stellar: { + network: "testnet", + networkPassphrase: Networks.TESTNET, + }, + }, + }); } function createTestApp(ttlString = "15m") { - const userRepository = new InMemoryUserRepository(); - const challengeRepository = new InMemoryChallengeRepository(); - const authService = new AuthService({ - userRepository, - challengeRepository, - config: { - jwt: { - secret: TEST_SECRET, - expiresIn: ttlString, - }, - auth: { - challengeTtlMs: 60_000, - }, - stellar: { - network: "testnet", - networkPassphrase: Networks.TESTNET, - }, - }, - }); - - return { - app: createApp({ authService }), - challengeRepository, - authService, - }; + const userRepository = new InMemoryUserRepository(); + const challengeRepository = new InMemoryChallengeRepository(); + const authService = new AuthService({ + userRepository, + challengeRepository, + config: { + jwt: { + secret: TEST_SECRET, + expiresIn: ttlString, + }, + auth: { + challengeTtlMs: 60_000, + }, + stellar: { + network: "testnet", + networkPassphrase: Networks.TESTNET, + }, + }, + }); + + return { + app: createApp({ authService }), + challengeRepository, + authService, + }; } // ── Unit Tests (AuthService internals) ── describe("JWT subject claim", () => { - it("should have sub equal to the wallet address used in the challenge", async () => { - const { app } = createTestApp(); - const keypair = Keypair.random(); - const walletAddress = keypair.publicKey(); - - // Complete full auth flow - const challengeRes = await request(app) - .post("/api/v1/auth/challenge") - .send({ publicKey: walletAddress }) - .expect(201); - - const { nonce, message } = challengeRes.body.challenge; - const signature = keypair.sign(Buffer.from(message, "utf8")).toString("base64"); - - const verifyRes = await request(app) - .post("/api/v1/auth/verify") - .send({ - publicKey: walletAddress, - nonce, - signature, - }) - .expect(200); - - const token = verifyRes.body.token; - - // Decode the token without verification to inspect the payload - const decoded = jwt.decode(token) as jwt.JwtPayload; - expect(decoded).not.toBeNull(); - expect(decoded!.sub).toBe(walletAddress); - }); + it("should have sub equal to the wallet address used in the challenge", async () => { + const { app } = createTestApp(); + const keypair = Keypair.random(); + const walletAddress = keypair.publicKey(); + + // Complete full auth flow + const challengeRes = await request(app) + .post("/api/v1/auth/challenge") + .send({ publicKey: walletAddress }) + .expect(201); + + const { nonce, message } = challengeRes.body.challenge; + const signature = keypair.sign(Buffer.from(message, "utf8")).toString("base64"); + + const verifyRes = await request(app) + .post("/api/v1/auth/verify") + .send({ + publicKey: walletAddress, + nonce, + signature, + }) + .expect(200); + + const token = verifyRes.body.token; + + // Decode the token without verification to inspect the payload + const decoded = jwt.decode(token) as jwt.JwtPayload; + expect(decoded).not.toBeNull(); + expect(decoded!.sub).toBe(walletAddress); + }); }); describe("JWT expiry", () => { - it("should be within 1 second of now + configured TTL", async () => { - const { app } = createTestApp("1h"); - const keypair = Keypair.random(); - const walletAddress = keypair.publicKey(); - - const challengeRes = await request(app) - .post("/api/v1/auth/challenge") - .send({ publicKey: walletAddress }) - .expect(201); - - const { nonce, message } = challengeRes.body.challenge; - const signature = keypair.sign(Buffer.from(message, "utf8")).toString("base64"); - - const verifyRes = await request(app) - .post("/api/v1/auth/verify") - .send({ - publicKey: walletAddress, - nonce, - signature, - }) - .expect(200); - - const token = verifyRes.body.token; - - // Decode to inspect exp claim - const decoded = jwt.decode(token) as jwt.JwtPayload; - expect(decoded).not.toBeNull(); - expect(decoded!.exp).toBeDefined(); - - const now = Math.floor(Date.now() / 1000); - const expectedExp = now + 3600; // 1h = 3600s - - // Allow 1 second tolerance - expect(Math.abs(decoded!.exp! - expectedExp)).toBeLessThanOrEqual(1); - }); + it("should be within 1 second of now + configured TTL", async () => { + const { app } = createTestApp("1h"); + const keypair = Keypair.random(); + const walletAddress = keypair.publicKey(); + + const challengeRes = await request(app) + .post("/api/v1/auth/challenge") + .send({ publicKey: walletAddress }) + .expect(201); + + const { nonce, message } = challengeRes.body.challenge; + const signature = keypair.sign(Buffer.from(message, "utf8")).toString("base64"); + + const verifyRes = await request(app) + .post("/api/v1/auth/verify") + .send({ + publicKey: walletAddress, + nonce, + signature, + }) + .expect(200); + + const token = verifyRes.body.token; + + // Decode to inspect exp claim + const decoded = jwt.decode(token) as jwt.JwtPayload; + expect(decoded).not.toBeNull(); + expect(decoded!.exp).toBeDefined(); + + const now = Math.floor(Date.now() / 1000); + const expectedExp = now + 3600; // 1h = 3600s + + // Allow 1 second tolerance + expect(Math.abs(decoded!.exp! - expectedExp)).toBeLessThanOrEqual(1); + }); }); describe("Tampered JWT", () => { - it("should be rejected with 401 by the verification middleware", async () => { - const { app } = createTestApp(); - const keypair = Keypair.random(); - const walletAddress = keypair.publicKey(); - - // Get a valid token first - const challengeRes = await request(app) - .post("/api/v1/auth/challenge") - .send({ publicKey: walletAddress }) - .expect(201); - - const { nonce, message } = challengeRes.body.challenge; - const signature = keypair.sign(Buffer.from(message, "utf8")).toString("base64"); - - const verifyRes = await request(app) - .post("/api/v1/auth/verify") - .send({ - publicKey: walletAddress, - nonce, - signature, - }) - .expect(200); - - const validToken = verifyRes.body.token; - - // Tamper with the payload by modifying the second part of the JWT - const parts = validToken.split("."); - const tamperedPayload = Buffer.from( - JSON.stringify({ sub: "tampered-wallet", stellarAddress: "tampered", iat: 0, exp: 9999999999 }), - ).toString("base64url"); - const tamperedToken = [parts[0], tamperedPayload, parts[2]].join("."); - - // Hit /me with the tampered token - await request(app) - .get("/api/v1/auth/me") - .set("Authorization", `Bearer ${tamperedToken}`) - .expect(401); - }); + it("should be rejected with 401 by the verification middleware", async () => { + const { app } = createTestApp(); + const keypair = Keypair.random(); + const walletAddress = keypair.publicKey(); + + // Get a valid token first + const challengeRes = await request(app) + .post("/api/v1/auth/challenge") + .send({ publicKey: walletAddress }) + .expect(201); + + const { nonce, message } = challengeRes.body.challenge; + const signature = keypair.sign(Buffer.from(message, "utf8")).toString("base64"); + + const verifyRes = await request(app) + .post("/api/v1/auth/verify") + .send({ + publicKey: walletAddress, + nonce, + signature, + }) + .expect(200); + + const validToken = verifyRes.body.token; + + // Tamper with the payload by modifying the second part of the JWT + const parts = validToken.split("."); + const tamperedPayload = Buffer.from( + JSON.stringify({ + sub: "tampered-wallet", + stellarAddress: "tampered", + iat: 0, + exp: 9999999999, + }) + ).toString("base64url"); + const tamperedToken = [parts[0], tamperedPayload, parts[2]].join("."); + + // Hit /me with the tampered token + await request(app) + .get("/api/v1/auth/me") + .set("Authorization", `Bearer ${tamperedToken}`) + .expect(401); + }); }); describe("Expired JWT", () => { - it("should be rejected with 401 when TTL is set to -1s in test config", async () => { - // Create a service with a -1s TTL (effectively already expired) - const { app } = createTestApp("-1s"); - const keypair = Keypair.random(); - const walletAddress = keypair.publicKey(); - - const challengeRes = await request(app) - .post("/api/v1/auth/challenge") - .send({ publicKey: walletAddress }) - .expect(201); - - const { nonce, message } = challengeRes.body.challenge; - const signature = keypair.sign(Buffer.from(message, "utf8")).toString("base64"); - - // The token should have exp in the past - const verifyRes = await request(app) - .post("/api/v1/auth/verify") - .send({ - publicKey: walletAddress, - nonce, - signature, - }) - .expect(200); - - const expiredToken = verifyRes.body.token; - - // The verify endpoint may still issue the token (it just signs it), - // so the token itself will be expired. Now try to use it. - await request(app) - .get("/api/v1/auth/me") - .set("Authorization", `Bearer ${expiredToken}`) - .expect(401); - }); -}); \ No newline at end of file + it("should be rejected with 401 when TTL is set to -1s in test config", async () => { + // Create a service with a -1s TTL (effectively already expired) + const { app } = createTestApp("-1s"); + const keypair = Keypair.random(); + const walletAddress = keypair.publicKey(); + + const challengeRes = await request(app) + .post("/api/v1/auth/challenge") + .send({ publicKey: walletAddress }) + .expect(201); + + const { nonce, message } = challengeRes.body.challenge; + const signature = keypair.sign(Buffer.from(message, "utf8")).toString("base64"); + + // The token should have exp in the past + const verifyRes = await request(app) + .post("/api/v1/auth/verify") + .send({ + publicKey: walletAddress, + nonce, + signature, + }) + .expect(200); + + const expiredToken = verifyRes.body.token; + + // The verify endpoint may still issue the token (it just signs it), + // so the token itself will be expired. Now try to use it. + await request(app) + .get("/api/v1/auth/me") + .set("Authorization", `Bearer ${expiredToken}`) + .expect(401); + }); +}); diff --git a/tests/auth.routes.test.ts b/tests/auth.routes.test.ts index d1ff9b4..7f451df 100644 --- a/tests/auth.routes.test.ts +++ b/tests/auth.routes.test.ts @@ -31,10 +31,47 @@ class InMemoryUserRepository implements UserRepositoryContract { } async findByStellarAddress(stellarAddress: string) { - return ( - [...this.users.values()].find((user) => user.stellarAddress === stellarAddress) ?? - null + return [...this.users.values()].find((user) => user.stellarAddress === stellarAddress) ?? null; + } + + async findByEmail(email: string) { + return [...this.users.values()].find((u) => u.email === email) ?? null; + } + + async findAll(options?: { + skip?: number; + take?: number; + cursor?: string; + order?: "ASC" | "DESC"; + }) { + let results = [...this.users.values()].filter((u) => !u.deletedAt); + results.sort((a, b) => + options?.order === "ASC" ? a.id.localeCompare(b.id) : b.id.localeCompare(a.id) ); + if (options?.cursor) { + const cursorIndex = results.findIndex((u) => u.id === options.cursor); + if (cursorIndex >= 0) { + results = results.slice(cursorIndex + 1); + } + } + if (options?.skip) { + results = results.slice(options.skip); + } + if (options?.take) { + results = results.slice(0, options.take); + } + return results; + } + + async count(options?: { cursor?: string }): Promise { + let results = [...this.users.values()].filter((u) => !u.deletedAt); + if (options?.cursor) { + const cursorIndex = results.findIndex((u) => u.id === options.cursor); + if (cursorIndex >= 0) { + results = results.slice(0, cursorIndex); + } + } + return results.length; } async save(user: Partial) { @@ -83,8 +120,7 @@ class InMemoryChallengeRepository implements ChallengeRepositoryContract { return ( [...this.challenges.values()].find( (challenge) => - challenge.stellarAddress === stellarAddress && - challenge.nonceHash === nonceHash, + challenge.stellarAddress === stellarAddress && challenge.nonceHash === nonceHash ) ?? null ); } @@ -99,6 +135,28 @@ class InMemoryChallengeRepository implements ChallengeRepositoryContract { challenge.consumedAt = consumedAt; return true; } + + async deleteExpired(before: Date): Promise { + let count = 0; + for (const [id, challenge] of this.challenges.entries()) { + if (challenge.expiresAt < before || (challenge.consumedAt && challenge.consumedAt < before)) { + this.challenges.delete(id); + count++; + } + } + return count; + } + + async countByStatus(status: "active" | "consumed" | "expired"): Promise { + const now = new Date(); + let count = 0; + for (const challenge of this.challenges.values()) { + if (status === "active" && !challenge.consumedAt && challenge.expiresAt > now) count++; + if (status === "consumed" && challenge.consumedAt) count++; + if (status === "expired" && !challenge.consumedAt && challenge.expiresAt <= now) count++; + } + return count; + } } function createTestServer(challengeTtlMs = 60_000) { @@ -129,7 +187,7 @@ function createTestServer(challengeTtlMs = 60_000) { } afterEach(() => { -jest.useRealTimers(); + jest.useRealTimers(); }); describe("Auth routes", () => { @@ -281,8 +339,8 @@ describe("Auth routes", () => { expect( [...challengeRepository.challenges.values()].some( - (challenge) => challenge.consumedAt !== null, - ), + (challenge) => challenge.consumedAt !== null + ) ).toBe(true); }); @@ -342,4 +400,4 @@ describe("Auth routes", () => { }, }); }); -}); \ No newline at end of file +}); diff --git a/tests/e2e/full-flow.e2e.test.ts b/tests/e2e/full-flow.e2e.test.ts index 7ffee60..28691a7 100644 --- a/tests/e2e/full-flow.e2e.test.ts +++ b/tests/e2e/full-flow.e2e.test.ts @@ -175,13 +175,21 @@ describe("E2E: Complete Invoice Financing Flow", () => { database: ":memory:", synchronize: true, logging: false, - entities: [User, Invoice, Investment, AuthChallenge, Transaction, KYCVerification, Notification], + entities: [ + User, + Invoice, + Investment, + AuthChallenge, + Transaction, + KYCVerification, + Notification, + ], }); await dataSource.initialize(); // Create services with mocked IPFS - const authService = createAuthService(dataSource, config); + const authService = createAuthService(dataSource, config, logger); const invoiceService = createInvoiceService(dataSource, mockIPFSService); const investmentService = createInvestmentService(dataSource); const settlementService = createSettlementService(dataSource); @@ -227,9 +235,7 @@ describe("E2E: Complete Invoice Financing Flow", () => { const { nonce, message } = challengeRes.body.challenge; // Sign the challenge message - const signature = sellerKeypair - .sign(Buffer.from(message, "utf8")) - .toString("hex"); + const signature = sellerKeypair.sign(Buffer.from(message, "utf8")).toString("hex"); // Verify challenge and get token const verifyRes = await request(app) @@ -258,9 +264,7 @@ describe("E2E: Complete Invoice Financing Flow", () => { const { nonce, message } = challengeRes.body.challenge; - const signature = investorKeypair - .sign(Buffer.from(message, "utf8")) - .toString("hex"); + const signature = investorKeypair.sign(Buffer.from(message, "utf8")).toString("hex"); const verifyRes = await request(app) .post("/api/v1/auth/verify") @@ -367,9 +371,7 @@ describe("E2E: Complete Invoice Financing Flow", () => { expect(invoice).toBeDefined(); expect(invoice?.status).toBe(InvoiceStatus.PUBLISHED); expect(invoice?.sellerId).toBe(sellerId); - expect(invoice?.ipfsHash).toBe( - "QmMockHash1234567890123456789012345678901234567890" - ); + expect(invoice?.ipfsHash).toBe("QmMockHash1234567890123456789012345678901234567890"); }); }); @@ -387,9 +389,7 @@ describe("E2E: Complete Invoice Financing Flow", () => { expect(Array.isArray(marketplaceRes.body.data)).toBe(true); expect(marketplaceRes.body.data.length).toBeGreaterThan(0); - const listedInvoice = marketplaceRes.body.data.find( - (inv: any) => inv.id === invoiceId - ); + const listedInvoice = marketplaceRes.body.data.find((inv: any) => inv.id === invoiceId); expect(listedInvoice).toBeDefined(); expect(listedInvoice.invoiceNumber).toBe("INV-E2E-001"); expect(toNum(listedInvoice.amount)).toBeCloseTo(10000, 2); diff --git a/tests/funding-deadline-validator.test.ts b/tests/funding-deadline-validator.test.ts index 6ddf482..e1a4442 100644 --- a/tests/funding-deadline-validator.test.ts +++ b/tests/funding-deadline-validator.test.ts @@ -184,7 +184,7 @@ describe("validateInvoiceForPublish deadline reporting", () => { }); const codes = validateInvoiceForPublish(invoice, NOW).map((e) => e.code); expect(codes).toEqual( - expect.arrayContaining(["FACE_VALUE_TOO_LOW", "DUE_DATE_IN_PAST", "MISSING_DOCUMENT"]), + expect.arrayContaining(["FACE_VALUE_TOO_LOW", "DUE_DATE_IN_PAST", "MISSING_DOCUMENT"]) ); }); }); diff --git a/tests/integration/admin-invoice-reject.integration.test.ts b/tests/integration/admin-invoice-reject.integration.test.ts index e525c8b..58f731d 100644 --- a/tests/integration/admin-invoice-reject.integration.test.ts +++ b/tests/integration/admin-invoice-reject.integration.test.ts @@ -1,6 +1,9 @@ import crypto from "crypto"; import { InvoiceService } from "../../src/services/invoice.service"; -import type { InvoiceRepositoryContract, NotificationSink } from "../../src/services/invoice.service"; +import type { + InvoiceRepositoryContract, + NotificationSink, +} from "../../src/services/invoice.service"; import { Invoice } from "../../src/models/Invoice.model"; import { InvoiceStatus, NotificationType } from "../../src/types/enums"; import { ServiceError } from "../../src/utils/service-error"; @@ -40,8 +43,7 @@ class InMemoryInvoiceRepository implements InvoiceRepositoryContract { async findOneBy(options: { id?: string; invoiceNumber?: string }) { for (const invoice of this.invoices.values()) { if (options.id && invoice.id === options.id) return invoice; - if (options.invoiceNumber && invoice.invoiceNumber === options.invoiceNumber) - return invoice; + if (options.invoiceNumber && invoice.invoiceNumber === options.invoiceNumber) return invoice; } return null; } @@ -55,7 +57,7 @@ class InMemoryInvoiceRepository implements InvoiceRepositoryContract { return [...this.invoices.values()].filter( (inv) => inv.sellerId === options.where.sellerId && - (options.where.status == null || inv.status === options.where.status), + (options.where.status == null || inv.status === options.where.status) ); } @@ -186,7 +188,7 @@ describe("Admin invoice reject: persists reason, transitions status, notifies se expect(notificationSink.sent).toHaveLength(1); await expect( - service.rejectInvoice({ invoiceId: invoice.id, rejectionReason: "Second reason" }), + service.rejectInvoice({ invoiceId: invoice.id, rejectionReason: "Second reason" }) ).rejects.toMatchObject({ code: "invoice_already_rejected", statusCode: 409, @@ -200,7 +202,7 @@ describe("Admin invoice reject: persists reason, transitions status, notifies se it("rejects with 404 when the invoice does not exist", async () => { await expect( - service.rejectInvoice({ invoiceId: crypto.randomUUID(), rejectionReason: "N/A" }), + service.rejectInvoice({ invoiceId: crypto.randomUUID(), rejectionReason: "N/A" }) ).rejects.toMatchObject({ code: "invoice_not_found", statusCode: 404 }); }); @@ -210,7 +212,7 @@ describe("Admin invoice reject: persists reason, transitions status, notifies se await repo.save(invoice); await expect( - service.rejectInvoice({ invoiceId: invoice.id, rejectionReason: "Too late" }), + service.rejectInvoice({ invoiceId: invoice.id, rejectionReason: "Too late" }) ).rejects.toMatchObject({ code: "invalid_status_transition", statusCode: 409, diff --git a/tests/integration/auth-jwt-validation.test.ts b/tests/integration/auth-jwt-validation.test.ts index 51e2b74..3aa514d 100644 --- a/tests/integration/auth-jwt-validation.test.ts +++ b/tests/integration/auth-jwt-validation.test.ts @@ -35,11 +35,47 @@ class InMemoryUserRepository implements UserRepositoryContract { } async findByStellarAddress(stellarAddress: string) { - return ( - [...this.users.values()].find( - (user) => user.stellarAddress === stellarAddress, - ) ?? null + return [...this.users.values()].find((user) => user.stellarAddress === stellarAddress) ?? null; + } + + async findByEmail(email: string) { + return [...this.users.values()].find((u) => u.email === email) ?? null; + } + + async findAll(options?: { + skip?: number; + take?: number; + cursor?: string; + order?: "ASC" | "DESC"; + }) { + let results = [...this.users.values()].filter((u) => !u.deletedAt); + results.sort((a, b) => + options?.order === "ASC" ? a.id.localeCompare(b.id) : b.id.localeCompare(a.id) ); + if (options?.cursor) { + const cursorIndex = results.findIndex((u) => u.id === options.cursor); + if (cursorIndex >= 0) { + results = results.slice(cursorIndex + 1); + } + } + if (options?.skip) { + results = results.slice(options.skip); + } + if (options?.take) { + results = results.slice(0, options.take); + } + return results; + } + + async count(options?: { cursor?: string }): Promise { + let results = [...this.users.values()].filter((u) => !u.deletedAt); + if (options?.cursor) { + const cursorIndex = results.findIndex((u) => u.id === options.cursor); + if (cursorIndex >= 0) { + results = results.slice(0, cursorIndex); + } + } + return results.length; } async save(user: Partial) { @@ -88,8 +124,7 @@ class InMemoryChallengeRepository implements ChallengeRepositoryContract { return ( [...this.challenges.values()].find( (challenge) => - challenge.stellarAddress === stellarAddress && - challenge.nonceHash === nonceHash, + challenge.stellarAddress === stellarAddress && challenge.nonceHash === nonceHash ) ?? null ); } @@ -104,6 +139,28 @@ class InMemoryChallengeRepository implements ChallengeRepositoryContract { challenge.consumedAt = consumedAt; return true; } + + async deleteExpired(before: Date): Promise { + let count = 0; + for (const [id, challenge] of this.challenges.entries()) { + if (challenge.expiresAt < before || (challenge.consumedAt && challenge.consumedAt < before)) { + this.challenges.delete(id); + count++; + } + } + return count; + } + + async countByStatus(status: "active" | "consumed" | "expired"): Promise { + const now = new Date(); + let count = 0; + for (const challenge of this.challenges.values()) { + if (status === "active" && !challenge.consumedAt && challenge.expiresAt > now) count++; + if (status === "consumed" && challenge.consumedAt) count++; + if (status === "expired" && !challenge.consumedAt && challenge.expiresAt <= now) count++; + } + return count; + } } // ── Test helpers ────────────────────────────────────────────────────────────── @@ -145,7 +202,7 @@ describe("JWT authentication validation", () => { userId: crypto.randomUUID(), }, "invalid-secret-key", - { expiresIn: "15m" }, + { expiresIn: "15m" } ); const response = await request(app) @@ -171,7 +228,7 @@ describe("JWT authentication validation", () => { userId: crypto.randomUUID(), }, VALID_JWT_SECRET, - { expiresIn: "-5m" }, + { expiresIn: "-5m" } ); const response = await request(app) diff --git a/tests/integration/concurrent-investment.integration.test.ts b/tests/integration/concurrent-investment.integration.test.ts index 0afcd83..3d98d5e 100644 --- a/tests/integration/concurrent-investment.integration.test.ts +++ b/tests/integration/concurrent-investment.integration.test.ts @@ -31,22 +31,22 @@ function createSerializedFakeDataSource(invoice: Invoice) { }, find: async ( entity: unknown, - options: { where: Record | Record[] }, + options: { where: Record | Record[] } ) => { if (entity === Investment) { const clauses = Array.isArray(options.where) ? options.where : [options.where]; return [...investments.values()].filter((inv) => clauses.some((clause) => Object.entries(clause).every( - ([k, v]) => (inv as unknown as Record)[k] === v, - ), - ), + ([k, v]) => (inv as unknown as Record)[k] === v + ) + ) ); } return []; }, create: (_entity: unknown, data: Partial) => - ({ id: crypto.randomUUID(), status: InvestmentStatus.PENDING, ...data } as Investment), + ({ id: crypto.randomUUID(), status: InvestmentStatus.PENDING, ...data }) as Investment, save: async (entity: unknown, data: Investment | Invoice) => { if (entity === Investment) investments.set((data as Investment).id, data as Investment); else if (entity === Invoice) invoices.set((data as Invoice).id, data as Invoice); @@ -153,7 +153,7 @@ describe("Concurrent investment: total committed amount must not exceed invoice // Total committed = 700 (seeded) + 200 (one success) = 900; well under 1000 const totalCommitted = [...investments.values()].reduce( (sum, inv) => sum.plus(new Decimal(inv.investmentAmount)), - new Decimal(0), + new Decimal(0) ); expect(totalCommitted.toFixed(4)).toBe("900.0000"); }); @@ -221,7 +221,7 @@ describe("Concurrent investment: total committed amount must not exceed invoice const totalCommitted = [...investments.values()].reduce( (sum, inv) => sum.plus(new Decimal(inv.investmentAmount)), - new Decimal(0), + new Decimal(0) ); expect(totalCommitted.toFixed(4)).toBe("500.0000"); @@ -251,8 +251,8 @@ describe("Concurrent investment: total committed amount must not exceed invoice investorId: investor.id, investmentAmount: "400.0000", investorWallet: investor.wallet, - }), - ), + }) + ) ); const fulfilled = results.filter((r) => r.status === "fulfilled"); @@ -269,7 +269,7 @@ describe("Concurrent investment: total committed amount must not exceed invoice expect(investments.size).toBe(2); const totalCommitted = [...investments.values()].reduce( (sum, inv) => sum.plus(new Decimal(inv.investmentAmount)), - new Decimal(0), + new Decimal(0) ); expect(totalCommitted.toFixed(4)).toBe("800.0000"); expect(totalCommitted.lte(new Decimal("1000.0000"))).toBe(true); diff --git a/tests/integration/expired-invoice.integration.test.ts b/tests/integration/expired-invoice.integration.test.ts index 0cf8cab..a717bf8 100644 --- a/tests/integration/expired-invoice.integration.test.ts +++ b/tests/integration/expired-invoice.integration.test.ts @@ -25,7 +25,7 @@ function createFakeDataSource(invoice: Invoice) { }, find: async () => [] as Investment[], create: (_entity: unknown, data: Partial) => - ({ id: crypto.randomUUID(), status: InvestmentStatus.PENDING, ...data } as Investment), + ({ id: crypto.randomUUID(), status: InvestmentStatus.PENDING, ...data }) as Investment, save: async (_entity: unknown, data: Investment | Invoice) => { if ((data as Investment).investmentAmount !== undefined) { investments.set((data as Investment).id, data as Investment); @@ -79,7 +79,7 @@ describe("Expired invoice rejects new investment commitments (issue #109)", () = investorId: crypto.randomUUID(), investmentAmount: "100.0000", investorWallet: INVESTOR_WALLET, - }), + }) ).rejects.toMatchObject({ code: "invoice_expired", statusCode: 422, @@ -97,7 +97,7 @@ describe("Expired invoice rejects new investment commitments (issue #109)", () = investorId: crypto.randomUUID(), investmentAmount: "100.0000", investorWallet: INVESTOR_WALLET, - }), + }) ).rejects.toBeInstanceOf(ServiceError); expect(investments.size).toBe(0); @@ -135,7 +135,7 @@ describe("Expired invoice rejects new investment commitments (issue #109)", () = investorId: crypto.randomUUID(), investmentAmount: "100.0000", investorWallet: INVESTOR_WALLET, - }), + }) ).resolves.toMatchObject({ status: InvestmentStatus.PENDING }); expect(investments.size).toBe(1); diff --git a/tests/integration/fractional-investment.integration.test.ts b/tests/integration/fractional-investment.integration.test.ts index 26fd98c..318bfce 100644 --- a/tests/integration/fractional-investment.integration.test.ts +++ b/tests/integration/fractional-investment.integration.test.ts @@ -11,14 +11,17 @@ import { InvoiceStatus, InvestmentStatus } from "../../src/types/enums"; * InvestmentService funding logic end to end without a live database. */ type FakeManager = { - createQueryBuilder: (entity: unknown, alias: string) => { + createQueryBuilder: ( + entity: unknown, + alias: string + ) => { setLock: () => unknown; where: (clause: string, params: { id: string }) => unknown; getOne: () => Promise; }; find: ( entity: unknown, - options: { where: Record | Record[] }, + options: { where: Record | Record[] } ) => Promise; create: (entity: unknown, data: Partial) => Investment | Partial; save: (entity: unknown, data: Investment | Invoice) => Promise; @@ -37,22 +40,22 @@ function createFakeDataSource(invoice: Invoice) { targetId = params.id; return builder; }, - getOne: async () => (targetId ? invoices.get(targetId) ?? null : null), + getOne: async () => (targetId ? (invoices.get(targetId) ?? null) : null), }; return builder; }, find: async ( entity: unknown, - options: { where: Record | Record[] }, + options: { where: Record | Record[] } ) => { if (entity === Investment) { const whereClauses = Array.isArray(options.where) ? options.where : [options.where]; return [...investments.values()].filter((investment) => whereClauses.some((clause) => Object.entries(clause).every( - ([key, value]) => (investment as unknown as Record)[key] === value, - ), - ), + ([key, value]) => (investment as unknown as Record)[key] === value + ) + ) ); } return []; @@ -110,9 +113,18 @@ describe("Fractional investment integration: splitting funded amount across mult const { dataSource, invoices, investments } = createFakeDataSource(invoice); const investmentService = new InvestmentService(dataSource); - const investorA = { id: crypto.randomUUID(), wallet: "GINVESTORA1234567890ABCDEFGHIJKLMNOPQRSTUVWXY" }; - const investorB = { id: crypto.randomUUID(), wallet: "GINVESTORB1234567890ABCDEFGHIJKLMNOPQRSTUVWXY" }; - const investorC = { id: crypto.randomUUID(), wallet: "GINVESTORC1234567890ABCDEFGHIJKLMNOPQRSTUVWXY" }; + const investorA = { + id: crypto.randomUUID(), + wallet: "GINVESTORA1234567890ABCDEFGHIJKLMNOPQRSTUVWXY", + }; + const investorB = { + id: crypto.randomUUID(), + wallet: "GINVESTORB1234567890ABCDEFGHIJKLMNOPQRSTUVWXY", + }; + const investorC = { + id: crypto.randomUUID(), + wallet: "GINVESTORC1234567890ABCDEFGHIJKLMNOPQRSTUVWXY", + }; const investmentA = await investmentService.createInvestment({ invoiceId: invoice.id, @@ -145,12 +157,12 @@ describe("Fractional investment integration: splitting funded amount across mult const totalFunded = allInvestments.reduce( (sum, investment) => sum.plus(new Decimal(investment.investmentAmount)), - new Decimal(0), + new Decimal(0) ); expect(totalFunded.toFixed(4)).toBe("10000.0000"); const sharePercentages = allInvestments.map((investment) => - new Decimal(investment.investmentAmount).dividedBy(totalFunded).times(100), + new Decimal(investment.investmentAmount).dividedBy(totalFunded).times(100) ); expect(sharePercentages[0].toFixed(2)).toBe("40.00"); diff --git a/tests/integration/investment-overflow.integration.test.ts b/tests/integration/investment-overflow.integration.test.ts index 176ce50..c6412e1 100644 --- a/tests/integration/investment-overflow.integration.test.ts +++ b/tests/integration/investment-overflow.integration.test.ts @@ -12,14 +12,17 @@ import { ServiceError } from "../../src/utils/service-error"; * InvestmentService funding logic end to end without a live database. */ type FakeManager = { - createQueryBuilder: (entity: unknown, alias: string) => { + createQueryBuilder: ( + entity: unknown, + alias: string + ) => { setLock: () => unknown; where: (clause: string, params: { id: string }) => unknown; getOne: () => Promise; }; find: ( entity: unknown, - options: { where: Record | Record[] }, + options: { where: Record | Record[] } ) => Promise; create: (entity: unknown, data: Partial) => Investment | Partial; save: (entity: unknown, data: Investment | Invoice) => Promise; @@ -38,22 +41,22 @@ function createFakeDataSource(invoice: Invoice) { targetId = params.id; return builder; }, - getOne: async () => (targetId ? invoices.get(targetId) ?? null : null), + getOne: async () => (targetId ? (invoices.get(targetId) ?? null) : null), }; return builder; }, find: async ( entity: unknown, - options: { where: Record | Record[] }, + options: { where: Record | Record[] } ) => { if (entity === Investment) { const whereClauses = Array.isArray(options.where) ? options.where : [options.where]; return [...investments.values()].filter((investment) => whereClauses.some((clause) => Object.entries(clause).every( - ([key, value]) => (investment as unknown as Record)[key] === value, - ), - ), + ([key, value]) => (investment as unknown as Record)[key] === value + ) + ) ); } return []; @@ -111,8 +114,14 @@ describe("Investment overflow integration: rejecting commitments exceeding invoi const { dataSource, invoices, investments } = createFakeDataSource(invoice); const investmentService = new InvestmentService(dataSource); - const investorA = { id: crypto.randomUUID(), wallet: "GINVESTORA1234567890ABCDEFGHIJKLMNOPQRSTUVWXY" }; - const investorB = { id: crypto.randomUUID(), wallet: "GINVESTORB1234567890ABCDEFGHIJKLMNOPQRSTUVWXY" }; + const investorA = { + id: crypto.randomUUID(), + wallet: "GINVESTORA1234567890ABCDEFGHIJKLMNOPQRSTUVWXY", + }; + const investorB = { + id: crypto.randomUUID(), + wallet: "GINVESTORB1234567890ABCDEFGHIJKLMNOPQRSTUVWXY", + }; await investmentService.createInvestment({ invoiceId: invoice.id, @@ -128,7 +137,7 @@ describe("Investment overflow integration: rejecting commitments exceeding invoi investorId: investorB.id, investmentAmount: "2000.0000", investorWallet: investorB.wallet, - }), + }) ).rejects.toMatchObject({ code: "INSUFFICIENT_CAPACITY", statusCode: 400, @@ -138,7 +147,7 @@ describe("Investment overflow integration: rejecting commitments exceeding invoi expect(investments.size).toBe(1); const totalFundedAfterRejection = [...investments.values()].reduce( (sum, investment) => sum.plus(new Decimal(investment.investmentAmount)), - new Decimal(0), + new Decimal(0) ); expect(totalFundedAfterRejection.toFixed(4)).toBe("4000.0000"); expect(invoices.get(invoice.id)?.status).toBe(InvoiceStatus.PUBLISHED); diff --git a/tests/integration/investor-dashboard.test.ts b/tests/integration/investor-dashboard.test.ts index c407472..bee8380 100644 --- a/tests/integration/investor-dashboard.test.ts +++ b/tests/integration/investor-dashboard.test.ts @@ -43,8 +43,18 @@ describe("Investor dashboard aggregate", () => { it("aggregates active, settled, and failed positions without leaking other investors", async () => { const investments = [ - seedInvestment({ id: "inv-1", investorId: walletAId, investmentAmount: "3000.0000", status: InvestmentStatus.PENDING }), - seedInvestment({ id: "inv-2", investorId: walletAId, investmentAmount: "2000.0000", status: InvestmentStatus.CONFIRMED }), + seedInvestment({ + id: "inv-1", + investorId: walletAId, + investmentAmount: "3000.0000", + status: InvestmentStatus.PENDING, + }), + seedInvestment({ + id: "inv-2", + investorId: walletAId, + investmentAmount: "2000.0000", + status: InvestmentStatus.CONFIRMED, + }), seedInvestment({ id: "inv-3", investorId: walletAId, @@ -115,7 +125,11 @@ describe("Investor dashboard aggregate", () => { it("excludes cancelled investments from the active count", async () => { mockRepository.find.mockResolvedValue([ - seedInvestment({ id: "inv-1", investmentAmount: "800.0000", status: InvestmentStatus.CANCELLED }), + seedInvestment({ + id: "inv-1", + investmentAmount: "800.0000", + status: InvestmentStatus.CANCELLED, + }), ]); const dashboard = await investmentService.getInvestorDashboard(walletAId); diff --git a/tests/integration/invoice-detail-commitments.integration.test.ts b/tests/integration/invoice-detail-commitments.integration.test.ts index cf1243c..7569003 100644 --- a/tests/integration/invoice-detail-commitments.integration.test.ts +++ b/tests/integration/invoice-detail-commitments.integration.test.ts @@ -17,9 +17,7 @@ function createFakeInvoiceService() { findOne: async ({ where: { id }, relations }) => { const invoice = invoices.get(id) ?? null; if (invoice && relations?.includes("investments")) { - const relatedInvestments = [...investments.values()].filter( - (inv) => inv.invoiceId === id, - ); + const relatedInvestments = [...investments.values()].filter((inv) => inv.invoiceId === id); invoice.investments = relatedInvestments; } return invoice; @@ -70,11 +68,7 @@ function createInvoice(overrides: Partial = {}): Invoice { } as Invoice; } -function createInvestment( - invoiceId: string, - investorWallet: string, - amount: string, -): Investment { +function createInvestment(invoiceId: string, investorWallet: string, amount: string): Investment { return { id: crypto.randomUUID(), invoiceId, @@ -146,7 +140,7 @@ describe("Invoice detail endpoint: investor commitments with share percentages", // Assert sum of all share percentages is exactly 100% const sumPercent = commitmentEntries.reduce( (sum, entry) => sum + parseFloat(entry.share_percent), - 0, + 0 ); expect(sumPercent).toBe(100); @@ -175,8 +169,7 @@ describe("Invoice detail endpoint: investor commitments with share percentages", investments.set(inv.id, inv); // Compute truncated wallet as the endpoint would - const truncated = - wallet.length >= 8 ? `${wallet.slice(0, 4)}…${wallet.slice(-4)}` : wallet; + const truncated = wallet.length >= 8 ? `${wallet.slice(0, 4)}…${wallet.slice(-4)}` : wallet; expect(truncated).toBe("GA5X…Z7W7"); }); -}); \ No newline at end of file +}); diff --git a/tests/integration/invoice-draft-update.integration.test.ts b/tests/integration/invoice-draft-update.integration.test.ts index 6d2798e..f8143d0 100644 --- a/tests/integration/invoice-draft-update.integration.test.ts +++ b/tests/integration/invoice-draft-update.integration.test.ts @@ -18,8 +18,7 @@ class InMemoryInvoiceRepository implements InvoiceRepositoryContract { async findOneBy(options: { id?: string; invoiceNumber?: string }) { for (const invoice of this.invoices.values()) { if (options.id && invoice.id === options.id) return invoice; - if (options.invoiceNumber && invoice.invoiceNumber === options.invoiceNumber) - return invoice; + if (options.invoiceNumber && invoice.invoiceNumber === options.invoiceNumber) return invoice; } return null; } @@ -33,7 +32,7 @@ class InMemoryInvoiceRepository implements InvoiceRepositoryContract { return [...this.invoices.values()].filter( (inv) => inv.sellerId === options.where.sellerId && - (options.where.status == null || inv.status === options.where.status), + (options.where.status == null || inv.status === options.where.status) ); } @@ -63,10 +62,7 @@ function noopIpfsService(): IPFSService { } as unknown as IPFSService; } -function seedDraftInvoice( - repo: InMemoryInvoiceRepository, - sellerId: string, -): Invoice { +function seedDraftInvoice(repo: InMemoryInvoiceRepository, sellerId: string): Invoice { const now = new Date(); const invoice: Invoice = { id: crypto.randomUUID(), @@ -152,7 +148,7 @@ describe("Invoice draft update integration (issue #112)", () => { invoiceId: invoice.id, sellerId: sellerA, customerName: "Should Not Update", - }), + }) ).rejects.toMatchObject({ code: "invalid_invoice_status", statusCode: 400, @@ -167,7 +163,7 @@ describe("Invoice draft update integration (issue #112)", () => { invoiceId: invoice.id, sellerId: sellerB, customerName: "Unauthorized Update", - }), + }) ).rejects.toMatchObject({ code: "unauthorized_invoice_access", statusCode: 403, diff --git a/tests/integration/invoice-publish-kyc-gate.integration.test.ts b/tests/integration/invoice-publish-kyc-gate.integration.test.ts index 46c626b..a5d2d53 100644 --- a/tests/integration/invoice-publish-kyc-gate.integration.test.ts +++ b/tests/integration/invoice-publish-kyc-gate.integration.test.ts @@ -33,8 +33,7 @@ class InMemoryInvoiceRepository implements InvoiceRepositoryContract { async findOneBy(options: { id?: string; invoiceNumber?: string }) { for (const invoice of this.invoices.values()) { if (options.id && invoice.id === options.id) return invoice; - if (options.invoiceNumber && invoice.invoiceNumber === options.invoiceNumber) - return invoice; + if (options.invoiceNumber && invoice.invoiceNumber === options.invoiceNumber) return invoice; } return null; } @@ -48,7 +47,7 @@ class InMemoryInvoiceRepository implements InvoiceRepositoryContract { return [...this.invoices.values()].filter( (inv) => inv.sellerId === options.where.sellerId && - (options.where.status == null || inv.status === options.where.status), + (options.where.status == null || inv.status === options.where.status) ); } @@ -96,10 +95,7 @@ function makeSeller(kycStatus: KYCStatus | null): User { * attached) so that a rejection in these tests can only be attributed to * the KYC gate, not incidental publish-validation failures. */ -function seedPublishableInvoice( - repo: InMemoryInvoiceRepository, - seller: User, -): Invoice { +function seedPublishableInvoice(repo: InMemoryInvoiceRepository, seller: User): Invoice { const now = new Date(); const invoice: Invoice = { id: crypto.randomUUID(), @@ -141,7 +137,7 @@ describe("Invoice publish: approved-seller KYC gate (issue #217)", () => { const invoice = seedPublishableInvoice(repo, seller); await expect( - service.publishInvoice({ invoiceId: invoice.id, sellerId: seller.id }), + service.publishInvoice({ invoiceId: invoice.id, sellerId: seller.id }) ).rejects.toMatchObject({ code: "kyc_approval_required", statusCode: 403, @@ -153,7 +149,7 @@ describe("Invoice publish: approved-seller KYC gate (issue #217)", () => { const invoice = seedPublishableInvoice(repo, seller); await expect( - service.publishInvoice({ invoiceId: invoice.id, sellerId: seller.id }), + service.publishInvoice({ invoiceId: invoice.id, sellerId: seller.id }) ).rejects.toMatchObject({ code: "kyc_approval_required", statusCode: 403, @@ -165,7 +161,7 @@ describe("Invoice publish: approved-seller KYC gate (issue #217)", () => { const invoice = seedPublishableInvoice(repo, seller); await expect( - service.publishInvoice({ invoiceId: invoice.id, sellerId: seller.id }), + service.publishInvoice({ invoiceId: invoice.id, sellerId: seller.id }) ).rejects.toMatchObject({ code: "kyc_approval_required", statusCode: 403, @@ -177,7 +173,7 @@ describe("Invoice publish: approved-seller KYC gate (issue #217)", () => { const invoice = seedPublishableInvoice(repo, seller); await expect( - service.publishInvoice({ invoiceId: invoice.id, sellerId: seller.id }), + service.publishInvoice({ invoiceId: invoice.id, sellerId: seller.id }) ).rejects.toMatchObject({ code: "kyc_approval_required", statusCode: 403, @@ -192,7 +188,7 @@ describe("Invoice publish: approved-seller KYC gate (issue #217)", () => { const invoice = seedPublishableInvoice(repo, seller); await expect( - service.publishInvoice({ invoiceId: invoice.id, sellerId: seller.id }), + service.publishInvoice({ invoiceId: invoice.id, sellerId: seller.id }) ).rejects.toMatchObject({ code: "kyc_approval_required" }); const persisted = await repo.findOne({ where: { id: invoice.id } }); @@ -221,7 +217,7 @@ describe("Invoice publish: approved-seller KYC gate (issue #217)", () => { const invoice = seedPublishableInvoice(repo, owner); await expect( - service.publishInvoice({ invoiceId: invoice.id, sellerId: impostor.id }), + service.publishInvoice({ invoiceId: invoice.id, sellerId: impostor.id }) ).rejects.toMatchObject({ code: "unauthorized_invoice_access", statusCode: 403, diff --git a/tests/integration/invoice-search.integration.test.ts b/tests/integration/invoice-search.integration.test.ts index b1df871..df25a12 100644 --- a/tests/integration/invoice-search.integration.test.ts +++ b/tests/integration/invoice-search.integration.test.ts @@ -1,5 +1,8 @@ import crypto from "crypto"; -import { MarketplaceService, MarketplaceRepositoryContract } from "../../src/services/marketplace.service"; +import { + MarketplaceService, + MarketplaceRepositoryContract, +} from "../../src/services/marketplace.service"; import { Invoice } from "../../src/models/Invoice.model"; import { InvoiceStatus } from "../../src/types/enums"; @@ -10,14 +13,13 @@ import { InvoiceStatus } from "../../src/types/enums"; function createFakeMarketplaceRepository(invoices: Invoice[]): MarketplaceRepositoryContract { return { async findPublishedInvoices(filters) { - const statuses = filters.status && filters.status.length > 0 ? filters.status : [InvoiceStatus.PUBLISHED]; + const statuses = + filters.status && filters.status.length > 0 ? filters.status : [InvoiceStatus.PUBLISHED]; let matched = invoices.filter((invoice) => statuses.includes(invoice.status)); if (filters.search) { const term = filters.search.toLowerCase(); - matched = matched.filter((inv) => - inv.customerName.toLowerCase().includes(term), - ); + matched = matched.filter((inv) => inv.customerName.toLowerCase().includes(term)); } return { invoices: matched, total: matched.length }; diff --git a/tests/integration/ipfs-upload.test.ts b/tests/integration/ipfs-upload.test.ts index 9677efd..4fd2a24 100644 --- a/tests/integration/ipfs-upload.test.ts +++ b/tests/integration/ipfs-upload.test.ts @@ -2,7 +2,9 @@ import { IPFSService } from "../../src/services/ipfs.service"; import { ServiceError } from "../../src/utils/service-error"; import { logger } from "../../src/observability/logger"; -function createMockFetch(responses: Array<{ ok: boolean; status: number; statusText: string; body: unknown }>) { +function createMockFetch( + responses: Array<{ ok: boolean; status: number; statusText: string; body: unknown }> +) { let callCount = 0; return jest.fn().mockImplementation(async () => { const response = responses[callCount] ?? responses[responses.length - 1]; @@ -36,8 +38,22 @@ describe("IPFS upload integration – retry backoff & error handling", () => { describe("429 rate limit followed by successful retry", () => { it("retries after 429 and succeeds on second attempt", async () => { const mockFetch = createMockFetch([ - { ok: false, status: 429, statusText: "Too Many Requests", body: { error: "Rate limit exceeded" } }, - { ok: true, status: 200, statusText: "OK", body: { IpfsHash: "QmRetrySuccess", PinSize: 1024, Timestamp: "2024-01-01T00:00:00.000Z" } }, + { + ok: false, + status: 429, + statusText: "Too Many Requests", + body: { error: "Rate limit exceeded" }, + }, + { + ok: true, + status: 200, + statusText: "OK", + body: { + IpfsHash: "QmRetrySuccess", + PinSize: 1024, + Timestamp: "2024-01-01T00:00:00.000Z", + }, + }, ]); const service = new IPFSService({ @@ -46,11 +62,23 @@ describe("IPFS upload integration – retry backoff & error handling", () => { fetchImplementation: mockFetch, }); - const firstAttempt = service.uploadFile(validBuffer, validFilename, validMimeType, "inv-1", 1); + const firstAttempt = service.uploadFile( + validBuffer, + validFilename, + validMimeType, + "inv-1", + 1 + ); await expect(firstAttempt).rejects.toThrow(ServiceError); await expect(firstAttempt).rejects.toMatchObject({ code: "ipfs_upload_failed" }); - const secondAttempt = service.uploadFile(validBuffer, validFilename, validMimeType, "inv-1", 2); + const secondAttempt = service.uploadFile( + validBuffer, + validFilename, + validMimeType, + "inv-1", + 2 + ); const result = await secondAttempt; expect(result.hash).toBe("QmRetrySuccess"); expect(mockFetch).toHaveBeenCalledTimes(2); @@ -82,7 +110,11 @@ describe("IPFS upload integration – retry backoff & error handling", () => { ok: true, status: 200, statusText: "OK", - json: async () => ({ IpfsHash: "QmBackoff", PinSize: 512, Timestamp: "2024-01-01T00:00:00.000Z" }), + json: async () => ({ + IpfsHash: "QmBackoff", + PinSize: 512, + Timestamp: "2024-01-01T00:00:00.000Z", + }), text: async () => "", }; }); @@ -117,11 +149,11 @@ describe("IPFS upload integration – retry backoff & error handling", () => { }); await expect( - service.uploadFile(oversizedBuffer, validFilename, validMimeType), + service.uploadFile(oversizedBuffer, validFilename, validMimeType) ).rejects.toThrow(ServiceError); await expect( - service.uploadFile(oversizedBuffer, validFilename, validMimeType), + service.uploadFile(oversizedBuffer, validFilename, validMimeType) ).rejects.toMatchObject({ code: "file_too_large", statusCode: 400 }); expect(mockFetch).not.toHaveBeenCalled(); @@ -137,7 +169,7 @@ describe("IPFS upload integration – retry backoff & error handling", () => { }); await expect( - service.uploadFile(validBuffer, "test.exe", "application/x-executable"), + service.uploadFile(validBuffer, "test.exe", "application/x-executable") ).rejects.toMatchObject({ code: "invalid_file_type", statusCode: 400 }); expect(mockFetch).not.toHaveBeenCalled(); @@ -157,13 +189,18 @@ describe("IPFS upload integration – retry backoff & error handling", () => { mockFetch.mockRejectedValue(new Error("ECONNREFUSED")); await expect( - service.uploadFile(validBuffer, validFilename, validMimeType), + service.uploadFile(validBuffer, validFilename, validMimeType) ).rejects.toMatchObject({ code: "ipfs_upload_error", statusCode: 500 }); }); it("reports non-2xx Pinata responses as ipfs_upload_failed", async () => { const mockFetch = createMockFetch([ - { ok: false, status: 500, statusText: "Internal Server Error", body: { error: "Pinata unavailable" } }, + { + ok: false, + status: 500, + statusText: "Internal Server Error", + body: { error: "Pinata unavailable" }, + }, ]); const service = new IPFSService({ @@ -173,13 +210,18 @@ describe("IPFS upload integration – retry backoff & error handling", () => { }); await expect( - service.uploadFile(validBuffer, validFilename, validMimeType), + service.uploadFile(validBuffer, validFilename, validMimeType) ).rejects.toMatchObject({ code: "ipfs_upload_failed", statusCode: 502 }); }); it("includes error details in thrown ServiceError", async () => { const mockFetch = createMockFetch([ - { ok: false, status: 402, statusText: "Payment Required", body: { error: "Subscription expired" } }, + { + ok: false, + status: 402, + statusText: "Payment Required", + body: { error: "Subscription expired" }, + }, ]); const service = new IPFSService({ @@ -206,7 +248,11 @@ describe("IPFS upload integration – retry backoff & error handling", () => { ok: true, status: 200, statusText: "OK", - body: { IpfsHash: "QmFinalHash999", PinSize: 2048, Timestamp: "2024-06-15T12:00:00.000Z" }, + body: { + IpfsHash: "QmFinalHash999", + PinSize: 2048, + Timestamp: "2024-06-15T12:00:00.000Z", + }, }, ]); @@ -216,7 +262,13 @@ describe("IPFS upload integration – retry backoff & error handling", () => { fetchImplementation: mockFetch, }); - const result = await service.uploadFile(validBuffer, validFilename, validMimeType, "inv-1", 1); + const result = await service.uploadFile( + validBuffer, + validFilename, + validMimeType, + "inv-1", + 1 + ); expect(result).toEqual({ hash: "QmFinalHash999", @@ -227,7 +279,12 @@ describe("IPFS upload integration – retry backoff & error handling", () => { it("sends correct Authorization header to Pinata", async () => { const mockFetch = createMockFetch([ - { ok: true, status: 200, statusText: "OK", body: { IpfsHash: "QmAuth", PinSize: 100, Timestamp: "2024-01-01T00:00:00.000Z" } }, + { + ok: true, + status: 200, + statusText: "OK", + body: { IpfsHash: "QmAuth", PinSize: 100, Timestamp: "2024-01-01T00:00:00.000Z" }, + }, ]); const service = new IPFSService({ @@ -243,7 +300,7 @@ describe("IPFS upload integration – retry backoff & error handling", () => { expect.objectContaining({ method: "POST", headers: { Authorization: "Bearer test-jwt-token" }, - }), + }) ); }); }); diff --git a/tests/integration/kyc-dev-approval-path.integration.test.ts b/tests/integration/kyc-dev-approval-path.integration.test.ts index 2620e40..ee97785 100644 --- a/tests/integration/kyc-dev-approval-path.integration.test.ts +++ b/tests/integration/kyc-dev-approval-path.integration.test.ts @@ -132,4 +132,4 @@ describe("KYC dev approval path", () => { expect(result.statusCode).toBe(401); expect(result.errorMessage).toContain("Authentication required"); }); -}); \ No newline at end of file +}); diff --git a/tests/integration/marketplace-cursor-pagination.integration.test.ts b/tests/integration/marketplace-cursor-pagination.integration.test.ts index a2e2010..9245e14 100644 --- a/tests/integration/marketplace-cursor-pagination.integration.test.ts +++ b/tests/integration/marketplace-cursor-pagination.integration.test.ts @@ -1,7 +1,10 @@ import "reflect-metadata"; import crypto from "crypto"; import { DataSource, getMetadataArgsStorage } from "typeorm"; -import { MarketplaceService, createMarketplaceService } from "../../src/services/marketplace.service"; +import { + MarketplaceService, + createMarketplaceService, +} from "../../src/services/marketplace.service"; import { Invoice } from "../../src/models/Invoice.model"; import { User } from "../../src/models/User.model"; import { Investment } from "../../src/models/Investment.model"; @@ -51,7 +54,15 @@ describe("Marketplace cursor pagination stable ordering (issue #226)", () => { database: ":memory:", synchronize: true, logging: false, - entities: [User, Invoice, Investment, Transaction, KYCVerification, Notification, AuthChallenge], + entities: [ + User, + Invoice, + Investment, + Transaction, + KYCVerification, + Notification, + AuthChallenge, + ], }); await dataSource.initialize(); @@ -63,7 +74,7 @@ describe("Marketplace cursor pagination stable ordering (issue #226)", () => { email: "seller-cursor@test.com", userType: UserType.SELLER, kycStatus: KYCStatus.APPROVED, - } as any), + } as any) )) as unknown as User; sellerId = seller.id; @@ -99,15 +110,12 @@ describe("Marketplace cursor pagination stable ordering (issue #226)", () => { status: InvoiceStatus.PUBLISHED, smartContractId: null, ...overrides, - } as any), + } as any) )) as unknown as Invoice; } /** Seeds `count` listings that all share the same primary sort value. */ - async function seedTiedListings( - count: number, - shared: Partial, - ): Promise { + async function seedTiedListings(count: number, shared: Partial): Promise { const ids: string[] = []; for (let i = 0; i < count; i += 1) { const invoice = await seedInvoice(shared); @@ -118,7 +126,7 @@ describe("Marketplace cursor pagination stable ordering (issue #226)", () => { async function collectAllPages( sortField: "amount" | "created_at", - limit: number, + limit: number ): Promise { const ordered: string[] = []; let cursor: string | null = null; @@ -132,7 +140,7 @@ describe("Marketplace cursor pagination stable ordering (issue #226)", () => { order: "DESC", limit, cursor, - }, + } ); page.data.forEach((invoice) => ordered.push(invoice.id)); pages += 1; @@ -147,7 +155,10 @@ describe("Marketplace cursor pagination stable ordering (issue #226)", () => { } it("pages over equal face values with deterministic id tie-ins (no repeats, no skips)", async () => { - const expected = await seedTiedListings(7, { amount: "5000.0000", status: InvoiceStatus.PUBLISHED }); + const expected = await seedTiedListings(7, { + amount: "5000.0000", + status: InvoiceStatus.PUBLISHED, + }); const idAsc = [...expected].sort((a, b) => a.localeCompare(b)); const ordered = await collectAllPages("amount", 2); @@ -169,7 +180,7 @@ describe("Marketplace cursor pagination stable ordering (issue #226)", () => { const page = await service.getPublishedInvoicesByCursor( { status: [InvoiceStatus.PUBLISHED] }, - { sortField: "amount", order: "DESC", limit: 10 }, + { sortField: "amount", order: "DESC", limit: 10 } ); const amounts = page.data.map((invoice) => Number(invoice.amount)); @@ -193,10 +204,7 @@ describe("Marketplace cursor pagination stable ordering (issue #226)", () => { // Force the created_at column to an identical value so the primary sort is // genuinely tied (CreateDateColumn otherwise timestamps each insert). - await dataSource.query( - `UPDATE invoices SET created_at = ?`, - [fixedCreatedAt.toISOString()], - ); + await dataSource.query(`UPDATE invoices SET created_at = ?`, [fixedCreatedAt.toISOString()]); const idAsc = [...ids].sort((a, b) => a.localeCompare(b)); const ordered = await collectAllPages("created_at", 3); @@ -210,20 +218,24 @@ describe("Marketplace cursor pagination stable ordering (issue #226)", () => { await expect( service.getPublishedInvoicesByCursor( { status: [InvoiceStatus.PUBLISHED] }, - { sortField: "amount", order: "DESC", limit: 10, cursor: "not-valid-cursor!!" }, - ), + { sortField: "amount", order: "DESC", limit: 10, cursor: "not-valid-cursor!!" } + ) ).rejects.toMatchObject({ code: "invalid_cursor", statusCode: 400 }); }); it("returns the expected client error when a cursor is encoded for a different field", async () => { const { encodeQueryCursor } = await import("../../src/utils/query-pagination.utils"); - const wrongFieldCursor = encodeQueryCursor("invoice.dueDate", "2026-01-31T00:00:00.000Z", "some-id"); + const wrongFieldCursor = encodeQueryCursor( + "invoice.dueDate", + "2026-01-31T00:00:00.000Z", + "some-id" + ); await expect( service.getPublishedInvoicesByCursor( { status: [InvoiceStatus.PUBLISHED] }, - { sortField: "amount", order: "DESC", limit: 10, cursor: wrongFieldCursor }, - ), + { sortField: "amount", order: "DESC", limit: 10, cursor: wrongFieldCursor } + ) ).rejects.toMatchObject({ code: "invalid_cursor", statusCode: 400 }); }); }); diff --git a/tests/integration/marketplace-listing.integration.test.ts b/tests/integration/marketplace-listing.integration.test.ts index a960050..c57f308 100644 --- a/tests/integration/marketplace-listing.integration.test.ts +++ b/tests/integration/marketplace-listing.integration.test.ts @@ -1,5 +1,8 @@ import crypto from "crypto"; -import { MarketplaceService, MarketplaceRepositoryContract } from "../../src/services/marketplace.service"; +import { + MarketplaceService, + MarketplaceRepositoryContract, +} from "../../src/services/marketplace.service"; import { Invoice } from "../../src/models/Invoice.model"; import { InvoiceStatus } from "../../src/types/enums"; @@ -12,7 +15,8 @@ import { InvoiceStatus } from "../../src/types/enums"; function createFakeMarketplaceRepository(invoices: Invoice[]): MarketplaceRepositoryContract { return { async findPublishedInvoices(filters) { - const statuses = filters.status && filters.status.length > 0 ? filters.status : [InvoiceStatus.PUBLISHED]; + const statuses = + filters.status && filters.status.length > 0 ? filters.status : [InvoiceStatus.PUBLISHED]; const matched = invoices.filter((invoice) => statuses.includes(invoice.status)); return { invoices: matched, total: matched.length }; }, @@ -50,7 +54,13 @@ describe("Marketplace listing integration: filtering invoices by status", () => const fundedInvoice = createInvoice({ status: InvoiceStatus.FUNDED }); const settledInvoice = createInvoice({ status: InvoiceStatus.SETTLED }); - const allInvoices = [draftInvoice, publishedInvoiceA, publishedInvoiceB, fundedInvoice, settledInvoice]; + const allInvoices = [ + draftInvoice, + publishedInvoiceA, + publishedInvoiceB, + fundedInvoice, + settledInvoice, + ]; function createService(): MarketplaceService { return new MarketplaceService({ @@ -65,7 +75,7 @@ describe("Marketplace listing integration: filtering invoices by status", () => expect(result.data).toHaveLength(2); expect(result.data.map((invoice) => invoice.id).sort()).toEqual( - [publishedInvoiceA.id, publishedInvoiceB.id].sort(), + [publishedInvoiceA.id, publishedInvoiceB.id].sort() ); expect(result.data.every((invoice) => invoice.status === InvoiceStatus.PUBLISHED)).toBe(true); }); @@ -73,7 +83,9 @@ describe("Marketplace listing integration: filtering invoices by status", () => it("returns only funded invoices when filtered by status=funded", async () => { const marketplaceService = createService(); - const result = await marketplaceService.getPublishedInvoices({ status: [InvoiceStatus.FUNDED] }); + const result = await marketplaceService.getPublishedInvoices({ + status: [InvoiceStatus.FUNDED], + }); expect(result.data).toHaveLength(1); expect(result.data[0].id).toBe(fundedInvoice.id); @@ -82,7 +94,9 @@ describe("Marketplace listing integration: filtering invoices by status", () => it("returns only settled invoices when filtered by status=settled", async () => { const marketplaceService = createService(); - const result = await marketplaceService.getPublishedInvoices({ status: [InvoiceStatus.SETTLED] }); + const result = await marketplaceService.getPublishedInvoices({ + status: [InvoiceStatus.SETTLED], + }); expect(result.data).toHaveLength(1); expect(result.data[0].id).toBe(settledInvoice.id); diff --git a/tests/integration/marketplace-sorting.test.ts b/tests/integration/marketplace-sorting.test.ts index f410fa1..7b99bb0 100644 --- a/tests/integration/marketplace-sorting.test.ts +++ b/tests/integration/marketplace-sorting.test.ts @@ -1,5 +1,8 @@ import crypto from "crypto"; -import { MarketplaceService, MarketplaceRepositoryContract } from "../../src/services/marketplace.service"; +import { + MarketplaceService, + MarketplaceRepositoryContract, +} from "../../src/services/marketplace.service"; import { Invoice } from "../../src/models/Invoice.model"; import { InvoiceStatus } from "../../src/types/enums"; @@ -8,160 +11,164 @@ import { InvoiceStatus } from "../../src/types/enums"; * Supports sorting by amount (face value) and due_date. */ function createFakeMarketplaceRepository(invoices: Invoice[]): MarketplaceRepositoryContract { - return { - async findPublishedInvoices(filters) { - const statuses = filters.status && filters.status.length > 0 ? filters.status : [InvoiceStatus.PUBLISHED]; - let matched = invoices.filter((invoice) => statuses.includes(invoice.status)); - - // Apply sorting - const sortColumn = filters.sort || "amount"; - const sortOrder = filters.sortOrder || "DESC"; - - matched = [...matched].sort((a, b) => { - let comparison: number; - - if (sortColumn === "amount") { - comparison = parseFloat(a.amount) - parseFloat(b.amount); - } else if (sortColumn === "due_date") { - comparison = a.dueDate.getTime() - b.dueDate.getTime(); - } else if (sortColumn === "discount_rate") { - comparison = parseFloat(a.discountRate) - parseFloat(b.discountRate); - } else if (sortColumn === "created_at") { - comparison = a.createdAt.getTime() - b.createdAt.getTime(); - } else { - comparison = 0; - } - - return sortOrder === "DESC" ? -comparison : comparison; - }); - - return { invoices: matched, total: matched.length }; - }, - }; + return { + async findPublishedInvoices(filters) { + const statuses = + filters.status && filters.status.length > 0 ? filters.status : [InvoiceStatus.PUBLISHED]; + let matched = invoices.filter((invoice) => statuses.includes(invoice.status)); + + // Apply sorting + const sortColumn = filters.sort || "amount"; + const sortOrder = filters.sortOrder || "DESC"; + + matched = [...matched].sort((a, b) => { + let comparison: number; + + if (sortColumn === "amount") { + comparison = parseFloat(a.amount) - parseFloat(b.amount); + } else if (sortColumn === "due_date") { + comparison = a.dueDate.getTime() - b.dueDate.getTime(); + } else if (sortColumn === "discount_rate") { + comparison = parseFloat(a.discountRate) - parseFloat(b.discountRate); + } else if (sortColumn === "created_at") { + comparison = a.createdAt.getTime() - b.createdAt.getTime(); + } else { + comparison = 0; + } + + return sortOrder === "DESC" ? -comparison : comparison; + }); + + return { invoices: matched, total: matched.length }; + }, + }; } function createInvoice(overrides: Partial = {}): Invoice { - return { - id: crypto.randomUUID(), - sellerId: crypto.randomUUID(), - invoiceNumber: `INV-${crypto.randomUUID().slice(0, 8)}`, - customerName: "Customer", - amount: "1000.0000", - discountRate: "5.00", - netAmount: "950.0000", - dueDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), - ipfsHash: "QmTestHash", - riskScore: null, - status: InvoiceStatus.DRAFT, - smartContractId: null, - createdAt: new Date(), - updatedAt: new Date(), - deletedAt: null, - seller: undefined as unknown as Invoice["seller"], - investments: [], - transactions: [], - ...overrides, - } as Invoice; + return { + id: crypto.randomUUID(), + sellerId: crypto.randomUUID(), + invoiceNumber: `INV-${crypto.randomUUID().slice(0, 8)}`, + customerName: "Customer", + amount: "1000.0000", + discountRate: "5.00", + netAmount: "950.0000", + dueDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), + ipfsHash: "QmTestHash", + riskScore: null, + status: InvoiceStatus.DRAFT, + smartContractId: null, + createdAt: new Date(), + updatedAt: new Date(), + deletedAt: null, + seller: undefined as unknown as Invoice["seller"], + investments: [], + transactions: [], + ...overrides, + } as Invoice; } describe("Marketplace sorting: default sort by face value descending", () => { - const now = Date.now(); - - // Seed 5 invoices with varying face values and distinct due dates - const invoice5000 = createInvoice({ - amount: "5000.0000", - status: InvoiceStatus.PUBLISHED, - invoiceNumber: "INV-5000", - dueDate: new Date(now + 10 * 24 * 60 * 60 * 1000), // 10 days - }); - const invoice50000 = createInvoice({ - amount: "50000.0000", - status: InvoiceStatus.PUBLISHED, - invoiceNumber: "INV-50000", - dueDate: new Date(now + 50 * 24 * 60 * 60 * 1000), // 50 days - }); - const invoice1000 = createInvoice({ - amount: "1000.0000", - status: InvoiceStatus.PUBLISHED, - invoiceNumber: "INV-1000", - dueDate: new Date(now + 5 * 24 * 60 * 60 * 1000), // 5 days - }); - const invoice25000 = createInvoice({ - amount: "25000.0000", - status: InvoiceStatus.PUBLISHED, - invoiceNumber: "INV-25000", - dueDate: new Date(now + 30 * 24 * 60 * 60 * 1000), // 30 days - }); - const invoice10000 = createInvoice({ - amount: "10000.0000", - status: InvoiceStatus.PUBLISHED, - invoiceNumber: "INV-10000", - dueDate: new Date(now + 20 * 24 * 60 * 60 * 1000), // 20 days + const now = Date.now(); + + // Seed 5 invoices with varying face values and distinct due dates + const invoice5000 = createInvoice({ + amount: "5000.0000", + status: InvoiceStatus.PUBLISHED, + invoiceNumber: "INV-5000", + dueDate: new Date(now + 10 * 24 * 60 * 60 * 1000), // 10 days + }); + const invoice50000 = createInvoice({ + amount: "50000.0000", + status: InvoiceStatus.PUBLISHED, + invoiceNumber: "INV-50000", + dueDate: new Date(now + 50 * 24 * 60 * 60 * 1000), // 50 days + }); + const invoice1000 = createInvoice({ + amount: "1000.0000", + status: InvoiceStatus.PUBLISHED, + invoiceNumber: "INV-1000", + dueDate: new Date(now + 5 * 24 * 60 * 60 * 1000), // 5 days + }); + const invoice25000 = createInvoice({ + amount: "25000.0000", + status: InvoiceStatus.PUBLISHED, + invoiceNumber: "INV-25000", + dueDate: new Date(now + 30 * 24 * 60 * 60 * 1000), // 30 days + }); + const invoice10000 = createInvoice({ + amount: "10000.0000", + status: InvoiceStatus.PUBLISHED, + invoiceNumber: "INV-10000", + dueDate: new Date(now + 20 * 24 * 60 * 60 * 1000), // 20 days + }); + + const allInvoices = [invoice5000, invoice50000, invoice1000, invoice25000, invoice10000]; + + function createService(): MarketplaceService { + return new MarketplaceService({ + marketplaceRepository: createFakeMarketplaceRepository(allInvoices), }); + } - const allInvoices = [invoice5000, invoice50000, invoice1000, invoice25000, invoice10000]; + it("returns invoices sorted by face value descending by default", async () => { + const marketplaceService = createService(); - function createService(): MarketplaceService { - return new MarketplaceService({ - marketplaceRepository: createFakeMarketplaceRepository(allInvoices), - }); - } + const result = await marketplaceService.getPublishedInvoices(); - it("returns invoices sorted by face value descending by default", async () => { - const marketplaceService = createService(); + expect(result.data).toHaveLength(5); - const result = await marketplaceService.getPublishedInvoices(); + // Expected order: $50,000, $25,000, $10,000, $5,000, $1,000 + const amounts = result.data.map((invoice) => parseFloat(invoice.amount)); + expect(amounts).toEqual([50000, 25000, 10000, 5000, 1000]); + }); - expect(result.data).toHaveLength(5); + it("respects ?sort=faceValue:asc parameter override", async () => { + const marketplaceService = createService(); - // Expected order: $50,000, $25,000, $10,000, $5,000, $1,000 - const amounts = result.data.map((invoice) => parseFloat(invoice.amount)); - expect(amounts).toEqual([50000, 25000, 10000, 5000, 1000]); + const result = await marketplaceService.getPublishedInvoices({ + sort: "amount", + sortOrder: "ASC", }); - it("respects ?sort=faceValue:asc parameter override", async () => { - const marketplaceService = createService(); + expect(result.data).toHaveLength(5); - const result = await marketplaceService.getPublishedInvoices( - { sort: "amount", sortOrder: "ASC" }, - ); + // Expected order: $1,000, $5,000, $10,000, $25,000, $50,000 + const amounts = result.data.map((invoice) => parseFloat(invoice.amount)); + expect(amounts).toEqual([1000, 5000, 10000, 25000, 50000]); + }); - expect(result.data).toHaveLength(5); + it("supports sorting by due_date ascending", async () => { + const marketplaceService = createService(); - // Expected order: $1,000, $5,000, $10,000, $25,000, $50,000 - const amounts = result.data.map((invoice) => parseFloat(invoice.amount)); - expect(amounts).toEqual([1000, 5000, 10000, 25000, 50000]); + const result = await marketplaceService.getPublishedInvoices({ + sort: "due_date", + sortOrder: "ASC", }); - it("supports sorting by due_date ascending", async () => { - const marketplaceService = createService(); + expect(result.data).toHaveLength(5); - const result = await marketplaceService.getPublishedInvoices( - { sort: "due_date", sortOrder: "ASC" }, - ); + // Verify due dates are in ascending order + const dueDates = result.data.map((invoice) => invoice.dueDate.getTime()); + for (let i = 1; i < dueDates.length; i++) { + expect(dueDates[i]).toBeGreaterThanOrEqual(dueDates[i - 1]); + } + }); - expect(result.data).toHaveLength(5); + it("supports sorting by due_date descending", async () => { + const marketplaceService = createService(); - // Verify due dates are in ascending order - const dueDates = result.data.map((invoice) => invoice.dueDate.getTime()); - for (let i = 1; i < dueDates.length; i++) { - expect(dueDates[i]).toBeGreaterThanOrEqual(dueDates[i - 1]); - } + const result = await marketplaceService.getPublishedInvoices({ + sort: "due_date", + sortOrder: "DESC", }); - it("supports sorting by due_date descending", async () => { - const marketplaceService = createService(); - - const result = await marketplaceService.getPublishedInvoices( - { sort: "due_date", sortOrder: "DESC" }, - ); - - expect(result.data).toHaveLength(5); + expect(result.data).toHaveLength(5); - // Verify due dates are in descending order - const dueDates = result.data.map((invoice) => invoice.dueDate.getTime()); - for (let i = 1; i < dueDates.length; i++) { - expect(dueDates[i]).toBeLessThanOrEqual(dueDates[i - 1]); - } - }); -}); \ No newline at end of file + // Verify due dates are in descending order + const dueDates = result.data.map((invoice) => invoice.dueDate.getTime()); + for (let i = 1; i < dueDates.length; i++) { + expect(dueDates[i]).toBeLessThanOrEqual(dueDates[i - 1]); + } + }); +}); diff --git a/tests/integration/notification-mark-read.integration.test.ts b/tests/integration/notification-mark-read.integration.test.ts index e698338..206f9a8 100644 --- a/tests/integration/notification-mark-read.integration.test.ts +++ b/tests/integration/notification-mark-read.integration.test.ts @@ -1,5 +1,9 @@ import crypto from "crypto"; -import { NotificationService, NotificationRepositoryContract, NotificationPage } from "../../src/services/notification.service"; +import { + NotificationService, + NotificationRepositoryContract, + NotificationPage, +} from "../../src/services/notification.service"; import { NotificationType } from "../../src/types/enums"; interface StoredNotification { @@ -15,7 +19,9 @@ interface StoredNotification { /** * In-memory notification repository for integration testing. */ -function createFakeNotificationRepository(): NotificationRepositoryContract & { store: StoredNotification[] } { +function createFakeNotificationRepository(): NotificationRepositoryContract & { + store: StoredNotification[]; +} { const store: StoredNotification[] = []; return { @@ -36,7 +42,9 @@ function createFakeNotificationRepository(): NotificationRepositoryContract & { }, async findByIdAndUserId(id, userId) { - return (store.find((n) => n.id === id && n.userId === userId) ?? null) as import("../../src/models/Notification.model").Notification | null; + return (store.find((n) => n.id === id && n.userId === userId) ?? null) as + | import("../../src/models/Notification.model").Notification + | null; }, async markRead(id, userId) { @@ -54,8 +62,16 @@ function createFakeNotificationRepository(): NotificationRepositoryContract & { const page = options.page ?? 1; const limit = options.limit ?? 20; return { - data: filtered.slice((page - 1) * limit, page * limit) as import("../../src/models/Notification.model").Notification[], - meta: { total: filtered.length, page, limit, totalPages: Math.ceil(filtered.length / limit) }, + data: filtered.slice( + (page - 1) * limit, + page * limit + ) as import("../../src/models/Notification.model").Notification[], + meta: { + total: filtered.length, + page, + limit, + totalPages: Math.ceil(filtered.length / limit), + }, }; }, }; @@ -75,7 +91,7 @@ describe("Notification mark-as-read integration", () => { "wallet-1", NotificationType.INVOICE, "Invoice published", - "Your invoice has been published.", + "Your invoice has been published." ); expect(notif.read).toBe(false); @@ -106,7 +122,7 @@ describe("Notification mark-as-read integration", () => { "wallet-1", NotificationType.PAYMENT, "Settlement", - "Settlement complete.", + "Settlement complete." ); await service.markNotificationRead(notif.id, "wallet-1"); @@ -120,11 +136,11 @@ describe("Notification mark-as-read integration", () => { "wallet-1", NotificationType.INVOICE, "Invoice", - "desc", + "desc" ); - await expect( - service.markNotificationRead(notif.id, "wallet-2"), - ).rejects.toThrow("Notification not found"); + await expect(service.markNotificationRead(notif.id, "wallet-2")).rejects.toThrow( + "Notification not found" + ); }); }); diff --git a/tests/integration/orchestrate-investment-funding.integration.test.ts b/tests/integration/orchestrate-investment-funding.integration.test.ts index e3165ee..b370b2a 100644 --- a/tests/integration/orchestrate-investment-funding.integration.test.ts +++ b/tests/integration/orchestrate-investment-funding.integration.test.ts @@ -1,9 +1,7 @@ import crypto from "crypto"; import { Investment } from "../../src/models/Investment.model"; import { Transaction } from "../../src/models/Transaction.model"; -import { - OrchestrateInvestmentFundingService, -} from "../../src/services/stellar/orchestrate-investment-funding.service"; +import { OrchestrateInvestmentFundingService } from "../../src/services/stellar/orchestrate-investment-funding.service"; import { InvestmentStatus, TransactionStatus, TransactionType } from "../../src/types/enums"; function createInvestment(overrides: Partial = {}): Investment { diff --git a/tests/integration/seller-dashboard-aggregates.integration.test.ts b/tests/integration/seller-dashboard-aggregates.integration.test.ts index d2486f2..0a80e3a 100644 --- a/tests/integration/seller-dashboard-aggregates.integration.test.ts +++ b/tests/integration/seller-dashboard-aggregates.integration.test.ts @@ -133,14 +133,14 @@ describe("Seller dashboard: aggregates scoped to authenticated seller only", () // Assert seller A published total is 2000 const sellerAPublished = sellerAResult.invoices.filter( - (inv) => inv.status === InvoiceStatus.PUBLISHED, + (inv) => inv.status === InvoiceStatus.PUBLISHED ); expect(sellerAPublished).toHaveLength(1); expect(sellerAPublished[0].amount).toBe("2000.0000"); // Assert seller A settled total is 3000 const sellerASettled = sellerAResult.invoices.filter( - (inv) => inv.status === InvoiceStatus.SETTLED, + (inv) => inv.status === InvoiceStatus.SETTLED ); expect(sellerASettled).toHaveLength(1); expect(sellerASettled[0].amount).toBe("3000.0000"); @@ -148,7 +148,7 @@ describe("Seller dashboard: aggregates scoped to authenticated seller only", () // No seller B invoices in seller A's result const sellerBInvoiceNumbers = ["INV-B-001", "INV-B-002"]; expect( - sellerAResult.invoices.some((inv) => sellerBInvoiceNumbers.includes(inv.invoiceNumber)), + sellerAResult.invoices.some((inv) => sellerBInvoiceNumbers.includes(inv.invoiceNumber)) ).toBe(false); // Call seller dashboard as seller B @@ -164,14 +164,14 @@ describe("Seller dashboard: aggregates scoped to authenticated seller only", () // Assert seller B published total is 5000 const sellerBPublished = sellerBResult.invoices.filter( - (inv) => inv.status === InvoiceStatus.PUBLISHED, + (inv) => inv.status === InvoiceStatus.PUBLISHED ); expect(sellerBPublished).toHaveLength(1); expect(sellerBPublished[0].amount).toBe("5000.0000"); // Assert seller B funded total is 4000 const sellerBFunded = sellerBResult.invoices.filter( - (inv) => inv.status === InvoiceStatus.FUNDED, + (inv) => inv.status === InvoiceStatus.FUNDED ); expect(sellerBFunded).toHaveLength(1); expect(sellerBFunded[0].amount).toBe("4000.0000"); @@ -179,7 +179,7 @@ describe("Seller dashboard: aggregates scoped to authenticated seller only", () // No seller A invoices in seller B's result const sellerAInvoiceNumbers = ["INV-A-001", "INV-A-002"]; expect( - sellerBResult.invoices.some((inv) => sellerAInvoiceNumbers.includes(inv.invoiceNumber)), + sellerBResult.invoices.some((inv) => sellerAInvoiceNumbers.includes(inv.invoiceNumber)) ).toBe(false); }); -}); \ No newline at end of file +}); diff --git a/tests/integration/seller-invoice-list.integration.test.ts b/tests/integration/seller-invoice-list.integration.test.ts index 0021209..ff3b975 100644 --- a/tests/integration/seller-invoice-list.integration.test.ts +++ b/tests/integration/seller-invoice-list.integration.test.ts @@ -52,7 +52,7 @@ describe("Seller invoice list integration: no cross-seller leakage", () => { email: "sellerA@test.com", userType: UserType.SELLER, kycStatus: KYCStatus.APPROVED, - }), + }) ); sellerB = await userRepository.save( @@ -61,7 +61,7 @@ describe("Seller invoice list integration: no cross-seller leakage", () => { email: "sellerB@test.com", userType: UserType.SELLER, kycStatus: KYCStatus.APPROVED, - }), + }) ); const invoiceRepository = dataSource.getRepository(Invoice); @@ -81,7 +81,7 @@ describe("Seller invoice list integration: no cross-seller leakage", () => { netAmount: "950.0000", dueDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), ...overrides, - }), + }) ); } @@ -99,7 +99,7 @@ describe("Seller invoice list integration: no cross-seller leakage", () => { netAmount: "1900.0000", dueDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), ...overrides, - }), + }) ); } @@ -128,7 +128,7 @@ describe("Seller invoice list integration: no cross-seller leakage", () => { const sellerBInvoiceNumbers = ["INV-B-001", "INV-B-002"]; expect( - result.invoices.some((invoice) => sellerBInvoiceNumbers.includes(invoice.invoiceNumber)), + result.invoices.some((invoice) => sellerBInvoiceNumbers.includes(invoice.invoiceNumber)) ).toBe(false); }); @@ -144,7 +144,7 @@ describe("Seller invoice list integration: no cross-seller leakage", () => { const statuses = result.invoices.map((invoice) => invoice.status); expect(statuses).toEqual( - expect.arrayContaining([InvoiceStatus.DRAFT, InvoiceStatus.PUBLISHED, InvoiceStatus.FUNDED]), + expect.arrayContaining([InvoiceStatus.DRAFT, InvoiceStatus.PUBLISHED, InvoiceStatus.FUNDED]) ); }); @@ -164,7 +164,7 @@ describe("Seller invoice list integration: no cross-seller leakage", () => { const statuses = result.invoices.map((invoice) => invoice.status); expect(statuses).toEqual( - expect.arrayContaining([InvoiceStatus.PUBLISHED, InvoiceStatus.SETTLED]), + expect.arrayContaining([InvoiceStatus.PUBLISHED, InvoiceStatus.SETTLED]) ); }); }); diff --git a/tests/integration/settlement.integration.test.ts b/tests/integration/settlement.integration.test.ts index e4677da..373bb3e 100644 --- a/tests/integration/settlement.integration.test.ts +++ b/tests/integration/settlement.integration.test.ts @@ -17,14 +17,17 @@ function createFakeDataSource(invoice: Invoice) { const investments = new Map(); type FakeManager = { - createQueryBuilder: (entity: unknown, alias: string) => { + createQueryBuilder: ( + entity: unknown, + alias: string + ) => { setLock: () => unknown; where: (clause: string, params: { id: string }) => unknown; getOne: () => Promise; }; find: ( entity: unknown, - options: { where: Record | Record[] }, + options: { where: Record | Record[] } ) => Promise; create: (entity: unknown, data: Partial) => Investment | Partial; save: (entity: unknown, data: Investment | Invoice) => Promise; @@ -39,22 +42,22 @@ function createFakeDataSource(invoice: Invoice) { targetId = params.id; return builder; }, - getOne: async () => (targetId ? invoices.get(targetId) ?? null : null), + getOne: async () => (targetId ? (invoices.get(targetId) ?? null) : null), }; return builder; }, find: async ( entity: unknown, - options: { where: Record | Record[] }, + options: { where: Record | Record[] } ) => { if (entity === Investment) { const whereClauses = Array.isArray(options.where) ? options.where : [options.where]; return [...investments.values()].filter((investment) => whereClauses.some((clause) => Object.entries(clause).every( - ([key, value]) => (investment as unknown as Record)[key] === value, - ), - ), + ([key, value]) => (investment as unknown as Record)[key] === value + ) + ) ); } return []; @@ -76,8 +79,7 @@ function createFakeDataSource(invoice: Invoice) { }; const dataSource = { - transaction: async (callback: (manager: FakeManager) => Promise) => - callback(manager), + transaction: async (callback: (manager: FakeManager) => Promise) => callback(manager), } as unknown as DataSource; return { dataSource, invoices, investments }; @@ -119,7 +121,7 @@ describe("Settlement integration: rejecting settlement of non-fully-funded invoi invoiceId: invoice.id, proceeds: "6000.0000", actorWallet: "GADMIN", - }), + }) ).rejects.toThrow(/Cannot settle an invoice with status published/); }); @@ -152,7 +154,7 @@ describe("Settlement integration: rejecting settlement of non-fully-funded invoi invoiceId: invoice.id, proceeds: "6000.0000", actorWallet: "GADMIN", - }), + }) ).rejects.toThrow(/Cannot settle an invoice with status published/); }); @@ -246,7 +248,7 @@ describe("Settlement integration: funding multiple investors then settling", () }); const returnByInvestor = new Map( - result.settlements.map((settlement) => [settlement.investorId, settlement.actualReturn]), + result.settlements.map((settlement) => [settlement.investorId, settlement.actualReturn]) ); expect(returnByInvestor.get(investorAId)).toBe("4400.0000"); @@ -257,7 +259,7 @@ describe("Settlement integration: funding multiple investors then settling", () const sumOfReturns = result.settlements.reduce( (sum, settlement) => sum + Number(settlement.actualReturn), - 0, + 0 ); expect(sumOfReturns).toBeCloseTo(6600, 4); }); @@ -300,7 +302,7 @@ describe("Settlement integration: funding multiple investors then settling", () }); const completionCall = infoSpy.mock.calls.find( - ([message]) => message === "Settlement flow completed.", + ([message]) => message === "Settlement flow completed." ); expect(completionCall).toBeDefined(); @@ -325,11 +327,11 @@ describe("Settlement integration: funding multiple investors then settling", () invoiceId: invoice.id, proceeds: "6600.0000", actorWallet: "GADMINWALLET1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ", - }), + }) ).rejects.toThrow(); const completionCall = infoSpy.mock.calls.find( - ([message]) => message === "Settlement flow completed.", + ([message]) => message === "Settlement flow completed." ); expect(completionCall).toBeUndefined(); }); diff --git a/tests/integration/webhook-delivery-idempotency.integration.test.ts b/tests/integration/webhook-delivery-idempotency.integration.test.ts index 01fb2fe..67a6c12 100644 --- a/tests/integration/webhook-delivery-idempotency.integration.test.ts +++ b/tests/integration/webhook-delivery-idempotency.integration.test.ts @@ -109,7 +109,7 @@ describe("Webhook delivery idempotency (issue #224)", () => { email: "idempotency@test.com", userType: "seller", kycStatus: "approved", - } as any), + } as any) )) as unknown as User; const subscriptionRepository = dataSource.getRepository(WebhookSubscription); @@ -120,7 +120,7 @@ describe("Webhook delivery idempotency (issue #224)", () => { secret: "whsec_subscription_secret", eventTypes: [EVENT_TYPE], active: true, - } as any), + } as any) )) as unknown as WebhookSubscription; }, 30000); @@ -174,7 +174,7 @@ describe("Webhook delivery idempotency (issue #224)", () => { "x-event-id": EVENT_ID, "x-signature": expect.any(String), }), - }), + }) ); // A delivered delivery record is persisted for this event + subscription. @@ -213,7 +213,7 @@ describe("Webhook delivery idempotency (issue #224)", () => { // The duplicate is identified as already handled in the delivery log lines. const alreadyHandled = loggerEntries.find( - (entry) => entry.level === "info" && entry.message === "webhook.event.already_handled", + (entry) => entry.level === "info" && entry.message === "webhook.event.already_handled" ); expect(alreadyHandled).toBeDefined(); expect(alreadyHandled?.metadata).toMatchObject({ @@ -248,7 +248,7 @@ describe("Webhook delivery idempotency (issue #224)", () => { // A failed delivery is NOT marked as already handled, so a later attempt // with the same event id is retried normally. const alreadyHandled = loggerEntries.find( - (entry) => entry.message === "webhook.event.already_handled", + (entry) => entry.message === "webhook.event.already_handled" ); expect(alreadyHandled).toBeUndefined(); }); diff --git a/tests/investment.routes.test.ts b/tests/investment.routes.test.ts index 476e04b..b20ae70 100644 --- a/tests/investment.routes.test.ts +++ b/tests/investment.routes.test.ts @@ -32,7 +32,7 @@ describe("Investment Routes", () => { createInvestmentRouter({ investmentService: mockInvestmentService, authService: mockAuthService, - }), + }) ); app.use(createErrorMiddleware(logger)); }); diff --git a/tests/investment.service.test.ts b/tests/investment.service.test.ts index 018bd06..3b31f3a 100644 --- a/tests/investment.service.test.ts +++ b/tests/investment.service.test.ts @@ -34,13 +34,14 @@ describe("InvestmentService", () => { investmentService = new InvestmentService(mockDataSource); }); - const getMockInvoice = () => ({ - id: "invoice-1", - sellerId: "seller-1", - amount: "1000.0000", - netAmount: "950.0000", - status: InvoiceStatus.PUBLISHED, - } as Invoice); + const getMockInvoice = () => + ({ + id: "invoice-1", + sellerId: "seller-1", + amount: "1000.0000", + netAmount: "950.0000", + status: InvoiceStatus.PUBLISHED, + }) as Invoice; it("should create a PENDING investment when within capacity", async () => { const mockInvoice = getMockInvoice(); @@ -89,9 +90,7 @@ describe("InvestmentService", () => { it("should reject investment if it exceeds capacity", async () => { const mockInvoice = getMockInvoice(); mockQueryBuilder.getOne.mockResolvedValue(mockInvoice); - mockEntityManager.find.mockResolvedValue([ - { investmentAmount: "500.0000" } as Investment, - ]); + mockEntityManager.find.mockResolvedValue([{ investmentAmount: "500.0000" } as Investment]); const input = { invoiceId: "invoice-1", @@ -101,7 +100,10 @@ describe("InvestmentService", () => { }; await expect(investmentService.createInvestment(input)).rejects.toThrow( - new ServiceError("INSUFFICIENT_CAPACITY", "Investment amount 500 exceeds remaining capacity 450"), + new ServiceError( + "INSUFFICIENT_CAPACITY", + "Investment amount 500 exceeds remaining capacity 450" + ) ); }); @@ -117,7 +119,7 @@ describe("InvestmentService", () => { }; await expect(investmentService.createInvestment(input)).rejects.toThrow( - new ServiceError("SELF_DEALING", "Investors cannot invest in their own invoices"), + new ServiceError("SELF_DEALING", "Investors cannot invest in their own invoices") ); }); @@ -130,7 +132,7 @@ describe("InvestmentService", () => { }; await expect(investmentService.createInvestment(input)).rejects.toThrow( - new ServiceError("INVALID_AMOUNT", "Investment amount must be greater than zero"), + new ServiceError("INVALID_AMOUNT", "Investment amount must be greater than zero") ); }); }); diff --git a/tests/invoice-lifecycle-log.test.ts b/tests/invoice-lifecycle-log.test.ts index 75ed4bc..bcbaedd 100644 --- a/tests/invoice-lifecycle-log.test.ts +++ b/tests/invoice-lifecycle-log.test.ts @@ -34,7 +34,7 @@ describe("logInvoiceTransition", () => { actor_wallet: "GABC...WXYZ", reason: "fully_funded", transitioned_at: expect.any(String), - }), + }) ); }); diff --git a/tests/invoice.routes.test.ts b/tests/invoice.routes.test.ts index 16e1010..474d989 100644 --- a/tests/invoice.routes.test.ts +++ b/tests/invoice.routes.test.ts @@ -28,10 +28,7 @@ describe("Invoice Routes", () => { }; const sellerId = "seller-123"; - const validToken = jwt.sign( - { sub: sellerId, stellarAddress: "GTEST123" }, - "test-secret", - ); + const validToken = jwt.sign({ sub: sellerId, stellarAddress: "GTEST123" }, "test-secret"); const mockInvoice = { id: "invoice-123", @@ -70,7 +67,7 @@ describe("Invoice Routes", () => { createInvoiceRouter({ invoiceService: mockInvoiceService, config: mockConfig as any, - }), + }) ); app.use(createErrorMiddleware(logger)); }); @@ -166,7 +163,7 @@ describe("Invoice Routes", () => { createInvoiceRouter({ invoiceService: mockInvoiceService, config: kycConfig as any, - }), + }) ); kycApp.use(createErrorMiddleware(logger)); @@ -198,7 +195,7 @@ describe("Invoice Routes", () => { it("should handle duplicate invoice number", async () => { mockInvoiceService.createInvoice.mockRejectedValue( - new ServiceError("invoice_number_exists", "Invoice number must be unique", 409), + new ServiceError("invoice_number_exists", "Invoice number must be unique", 409) ); await request(app) @@ -285,9 +282,7 @@ describe("Invoice Routes", () => { }); it("should reject unauthenticated requests", async () => { - await request(app) - .get("/api/v1/invoices") - .expect(401); + await request(app).get("/api/v1/invoices").expect(401); }); it("should validate pagination parameters", async () => { @@ -313,10 +308,7 @@ describe("Invoice Routes", () => { data: mockInvoice, }); - expect(mockInvoiceService.getInvoiceById).toHaveBeenCalledWith( - "invoice-123", - sellerId, - ); + expect(mockInvoiceService.getInvoiceById).toHaveBeenCalledWith("invoice-123", sellerId); }); it("should return 404 when invoice not found", async () => { @@ -333,8 +325,8 @@ describe("Invoice Routes", () => { new ServiceError( "unauthorized_invoice_access", "You do not have access to this invoice", - 403, - ), + 403 + ) ); await request(app) @@ -344,9 +336,7 @@ describe("Invoice Routes", () => { }); it("should reject unauthenticated requests", async () => { - await request(app) - .get("/api/v1/invoices/invoice-123") - .expect(401); + await request(app).get("/api/v1/invoices/invoice-123").expect(401); }); }); @@ -400,8 +390,8 @@ describe("Invoice Routes", () => { new ServiceError( "invalid_invoice_status", "Cannot update invoice in published status. Only draft invoices can be updated.", - 400, - ), + 400 + ) ); await request(app) @@ -418,8 +408,8 @@ describe("Invoice Routes", () => { new ServiceError( "unauthorized_invoice_access", "You can only update your own invoices", - 403, - ), + 403 + ) ); await request(app) @@ -450,19 +440,12 @@ describe("Invoice Routes", () => { .set("Authorization", `Bearer ${validToken}`) .expect(204); - expect(mockInvoiceService.deleteInvoice).toHaveBeenCalledWith( - "invoice-123", - sellerId, - ); + expect(mockInvoiceService.deleteInvoice).toHaveBeenCalledWith("invoice-123", sellerId); }); it("should reject deletion of published invoice", async () => { mockInvoiceService.deleteInvoice.mockRejectedValue( - new ServiceError( - "invalid_invoice_status", - "Cannot delete invoice in published status", - 400, - ), + new ServiceError("invalid_invoice_status", "Cannot delete invoice in published status", 400) ); await request(app) @@ -476,8 +459,8 @@ describe("Invoice Routes", () => { new ServiceError( "unauthorized_invoice_access", "You can only delete your own invoices", - 403, - ), + 403 + ) ); await request(app) @@ -487,9 +470,7 @@ describe("Invoice Routes", () => { }); it("should reject unauthenticated requests", async () => { - await request(app) - .delete("/api/v1/invoices/invoice-123") - .expect(401); + await request(app).delete("/api/v1/invoices/invoice-123").expect(401); }); }); @@ -523,8 +504,8 @@ describe("Invoice Routes", () => { new ServiceError( "invalid_status_transition", "Cannot transition from settled to published", - 400, - ), + 400 + ) ); await request(app) @@ -538,8 +519,8 @@ describe("Invoice Routes", () => { new ServiceError( "unauthorized_invoice_access", "You can only publish your own invoices", - 403, - ), + 403 + ) ); await request(app) @@ -549,9 +530,7 @@ describe("Invoice Routes", () => { }); it("should reject unauthenticated requests", async () => { - await request(app) - .post("/api/v1/invoices/invoice-123/publish") - .expect(401); + await request(app).post("/api/v1/invoices/invoice-123/publish").expect(401); }); }); @@ -606,7 +585,7 @@ describe("Invoice Routes", () => { it("should handle service errors", async () => { mockInvoiceService.uploadDocument.mockRejectedValue( - new ServiceError("invoice_not_found", "Invoice not found", 404), + new ServiceError("invoice_not_found", "Invoice not found", 404) ); await request(app) @@ -621,8 +600,8 @@ describe("Invoice Routes", () => { new ServiceError( "unauthorized_invoice_access", "You can only upload documents to your own invoices", - 403, - ), + 403 + ) ); await request(app) diff --git a/tests/invoice.service.test.ts b/tests/invoice.service.test.ts index 0c5c8cd..f9a550f 100644 --- a/tests/invoice.service.test.ts +++ b/tests/invoice.service.test.ts @@ -121,7 +121,7 @@ describe("InvoiceService", () => { }); expect(mockInvoiceRepository.create).toHaveBeenCalledWith( - expect.objectContaining({ netAmount: "29.8401" }), + expect.objectContaining({ netAmount: "29.8401" }) ); expect(result.netAmount).toBe("29.8401"); }); @@ -379,7 +379,10 @@ describe("InvoiceService", () => { ...mockInvoice, dueDate: new Date(Date.now() + 48 * 60 * 60 * 1000), ipfsHash: "QmTestHash", - seller: { kycStatus: "approved", stellarAddress: "GSELLERWALLET1234567890ABCDEFGHIJKLMNOPQRSTUV" }, + seller: { + kycStatus: "approved", + stellarAddress: "GSELLERWALLET1234567890ABCDEFGHIJKLMNOPQRSTUV", + }, } as Invoice; it("should transition draft invoice to published", async () => { @@ -399,7 +402,10 @@ describe("InvoiceService", () => { const soonDueInvoice = { ...mockInvoice, dueDate: new Date(Date.now() + 60 * 60 * 1000), // 1 hour in future - seller: { kycStatus: "approved", stellarAddress: "GSELLERWALLET1234567890ABCDEFGHIJKLMNOPQRSTUV" }, + seller: { + kycStatus: "approved", + stellarAddress: "GSELLERWALLET1234567890ABCDEFGHIJKLMNOPQRSTUV", + }, }; mockInvoiceRepository.findOne.mockResolvedValue(soonDueInvoice); @@ -419,7 +425,10 @@ describe("InvoiceService", () => { ...mockInvoice, status: InvoiceStatus.SETTLED, dueDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), - seller: { kycStatus: "approved", stellarAddress: "GSELLERWALLET1234567890ABCDEFGHIJKLMNOPQRSTUV" }, + seller: { + kycStatus: "approved", + stellarAddress: "GSELLERWALLET1234567890ABCDEFGHIJKLMNOPQRSTUV", + }, }; mockInvoiceRepository.findOne.mockResolvedValue(settledInvoice); @@ -466,7 +475,10 @@ describe("InvoiceService", () => { const invoiceWithPendingKYC = { ...publishableInvoice, status: InvoiceStatus.DRAFT, - seller: { kycStatus: "pending", stellarAddress: "GSELLERWALLET1234567890ABCDEFGHIJKLMNOPQRSTUV" }, + seller: { + kycStatus: "pending", + stellarAddress: "GSELLERWALLET1234567890ABCDEFGHIJKLMNOPQRSTUV", + }, }; mockInvoiceRepository.findOne.mockResolvedValue(invoiceWithPendingKYC); @@ -489,7 +501,7 @@ describe("InvoiceService", () => { invoiceService.publishInvoice({ invoiceId: "invoice-123", sellerId: "seller-456", - }), + }) ).rejects.toMatchObject({ code: "invoice_not_publishable", statusCode: 400, diff --git a/tests/kyc.controller.test.ts b/tests/kyc.controller.test.ts index 9e0ae31..20fec6d 100644 --- a/tests/kyc.controller.test.ts +++ b/tests/kyc.controller.test.ts @@ -12,7 +12,10 @@ function response() { describe("KYC webhook controller", () => { it("rejects an invalid provider signature", async () => { - const service = { verifyWebhookSignature: jest.fn().mockReturnValue(false), processWebhook: jest.fn() }; + const service = { + verifyWebhookSignature: jest.fn().mockReturnValue(false), + processWebhook: jest.fn(), + }; const controller = createKycController(service as any); const res = response(); await controller.webhook({ body: Buffer.from("{}"), header: () => "bad" } as any, res); diff --git a/tests/kyc.service.test.ts b/tests/kyc.service.test.ts index 8398497..e4bc3a4 100644 --- a/tests/kyc.service.test.ts +++ b/tests/kyc.service.test.ts @@ -23,12 +23,20 @@ function createHarness() { findOne: jest.fn().mockResolvedValue(verification), }; const manager = { - getRepository: jest.fn((entity) => entity.name === "User" ? userRepository : verificationRepository), + getRepository: jest.fn((entity) => + entity.name === "User" ? userRepository : verificationRepository + ), }; const dataSource = { transaction: jest.fn(async (callback) => callback(manager)), }; - const appLogger = { info: jest.fn(), debug: jest.fn(), warn: jest.fn(), error: jest.fn(), child: jest.fn() }; + const appLogger = { + info: jest.fn(), + debug: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + child: jest.fn(), + }; const service = new KycService(dataSource as any, "webhook-secret", appLogger as any); return { service, userRepository, verificationRepository, appLogger }; } @@ -40,10 +48,12 @@ describe("KycService", () => { providerReference: "provider-123", }); expect(result.status).toBe(KYCStatus.PENDING); - expect(verificationRepository.create).toHaveBeenCalledWith(expect.objectContaining({ - verificationType: KYCVerificationType.IDENTITY, - documents: { providerReference: "provider-123" }, - })); + expect(verificationRepository.create).toHaveBeenCalledWith( + expect.objectContaining({ + verificationType: KYCVerificationType.IDENTITY, + documents: { providerReference: "provider-123" }, + }) + ); expect(userRepository.update).toHaveBeenCalledWith("user-1", { kycStatus: KYCStatus.PENDING, isKycVerified: false, @@ -65,12 +75,20 @@ describe("KycService", () => { const { service, userRepository, verificationRepository, appLogger } = createHarness(); await service.processWebhook({ userId: "user-1", status }); expect(verificationRepository.save).toHaveBeenCalledWith(expect.objectContaining({ status })); - expect(userRepository.update).toHaveBeenCalledWith("user-1", { kycStatus: status, isKycVerified }); - expect(appLogger.info).toHaveBeenCalledWith("kyc.webhook.processed", expect.objectContaining({ status })); + expect(userRepository.update).toHaveBeenCalledWith("user-1", { + kycStatus: status, + isKycVerified, + }); + expect(appLogger.info).toHaveBeenCalledWith( + "kyc.webhook.processed", + expect.objectContaining({ status }) + ); }); it("rejects unsupported webhook transitions", async () => { const { service } = createHarness(); - await expect(service.processWebhook({ userId: "user-1", status: KYCStatus.PENDING })).rejects.toMatchObject({ statusCode: 400 }); + await expect( + service.processWebhook({ userId: "user-1", status: KYCStatus.PENDING }) + ).rejects.toMatchObject({ statusCode: 400 }); }); }); diff --git a/tests/kyc.test.ts b/tests/kyc.test.ts index b872b03..2f28f6a 100644 --- a/tests/kyc.test.ts +++ b/tests/kyc.test.ts @@ -3,15 +3,11 @@ import { KYCStatus } from "@/types/enums"; describe("KYC check", () => { it("blocks non-approved users", () => { - expect(() => - requireApprovedKYC({ kycStatus: KYCStatus.PENDING }) - ).toThrow(); + expect(() => requireApprovedKYC({ kycStatus: KYCStatus.PENDING })).toThrow(); }); it("allows approved users", () => { - expect(() => - requireApprovedKYC({ kycStatus: KYCStatus.APPROVED }) - ).not.toThrow(); + expect(() => requireApprovedKYC({ kycStatus: KYCStatus.APPROVED })).not.toThrow(); }); }); @@ -23,4 +19,4 @@ describe("truncateWalletAddress", () => { it("returns short addresses unchanged", () => { expect(truncateWalletAddress("GABC")).toBe("GABC"); }); -}); \ No newline at end of file +}); diff --git a/tests/marketplace.repository.test.ts b/tests/marketplace.repository.test.ts index 8df22fc..1f90812 100644 --- a/tests/marketplace.repository.test.ts +++ b/tests/marketplace.repository.test.ts @@ -113,11 +113,11 @@ describe("TypeORMMarketplaceRepository", () => { expect(mockQueryBuilder.andWhere).toHaveBeenCalledWith( "CAST(invoice.amount AS DECIMAL) >= :minAmount", - { minAmount: 500 }, + { minAmount: 500 } ); expect(mockQueryBuilder.andWhere).toHaveBeenCalledWith( "CAST(invoice.amount AS DECIMAL) <= :maxAmount", - { maxAmount: 2000 }, + { maxAmount: 2000 } ); }); @@ -196,14 +196,20 @@ describe("TypeORMMarketplaceRepository", () => { // Should only have the base where clause for deleted_at expect(mockQueryBuilder.where).toHaveBeenCalledTimes(1); expect(mockQueryBuilder.where).toHaveBeenCalledWith("invoice.deleted_at IS NULL"); - + // Should not have additional where clauses for optional filters (except default status) const andWhereCalls = mockQueryBuilder.andWhere.mock.calls; - expect(andWhereCalls.some(call => typeof call[0] === 'string' && call[0].includes("due_date"))).toBe(false); - expect(andWhereCalls.some(call => typeof call[0] === 'string' && call[0].includes("amount"))).toBe(false); - + expect( + andWhereCalls.some((call) => typeof call[0] === "string" && call[0].includes("due_date")) + ).toBe(false); + expect( + andWhereCalls.some((call) => typeof call[0] === "string" && call[0].includes("amount")) + ).toBe(false); + // Status filter should be applied with default value - expect(andWhereCalls.some(call => typeof call[0] === 'string' && call[0].includes("status"))).toBe(true); + expect( + andWhereCalls.some((call) => typeof call[0] === "string" && call[0].includes("status")) + ).toBe(true); }); it("should return both invoices and total count", async () => { @@ -212,7 +218,7 @@ describe("TypeORMMarketplaceRepository", () => { const result = await marketplaceService.getPublishedInvoices( { status: [InvoiceStatus.PUBLISHED] }, - { page: 1, limit: 20 }, + { page: 1, limit: 20 } ); expect(result.meta.total).toBe(25); @@ -221,4 +227,4 @@ describe("TypeORMMarketplaceRepository", () => { expect(mockQueryBuilder.getMany).toHaveBeenCalled(); }); }); -}); \ No newline at end of file +}); diff --git a/tests/marketplace.routes.test.ts b/tests/marketplace.routes.test.ts index 439c7f0..8bc9ab0 100644 --- a/tests/marketplace.routes.test.ts +++ b/tests/marketplace.routes.test.ts @@ -20,7 +20,7 @@ describe("Marketplace Routes", () => { "/api/v1/marketplace", createMarketplaceRouter({ marketplaceService: mockMarketplaceService, - }), + }) ); app.use(createErrorMiddleware(logger)); }); @@ -51,9 +51,7 @@ describe("Marketplace Routes", () => { it("should return published invoices with default parameters", async () => { mockMarketplaceService.getPublishedInvoices.mockResolvedValue(mockResponse); - const response = await request(app) - .get("/api/v1/marketplace/invoices") - .expect(200); + const response = await request(app).get("/api/v1/marketplace/invoices").expect(200); expect(response.body).toEqual({ success: true, @@ -70,7 +68,7 @@ describe("Marketplace Routes", () => { sort: "amount", sortOrder: "DESC", }, - { page: 1, limit: 20 }, + { page: 1, limit: 20 } ); }); @@ -82,10 +80,10 @@ describe("Marketplace Routes", () => { .query({ page: 2, limit: 10 }) .expect(200); - expect(mockMarketplaceService.getPublishedInvoices).toHaveBeenCalledWith( - expect.any(Object), - { page: 2, limit: 10 }, - ); + expect(mockMarketplaceService.getPublishedInvoices).toHaveBeenCalledWith(expect.any(Object), { + page: 2, + limit: 10, + }); }); it("should handle status filter as single value", async () => { @@ -100,7 +98,7 @@ describe("Marketplace Routes", () => { expect.objectContaining({ status: ["published"], }), - expect.any(Object), + expect.any(Object) ); }); @@ -116,7 +114,7 @@ describe("Marketplace Routes", () => { expect.objectContaining({ status: ["published", "funded"], }), - expect.any(Object), + expect.any(Object) ); }); @@ -133,7 +131,7 @@ describe("Marketplace Routes", () => { minAmount: 500, maxAmount: 2000, }), - expect.any(Object), + expect.any(Object) ); }); @@ -149,7 +147,7 @@ describe("Marketplace Routes", () => { expect.objectContaining({ dueBefore: new Date("2024-12-31T23:59:59.999Z"), }), - expect.any(Object), + expect.any(Object) ); }); @@ -166,7 +164,7 @@ describe("Marketplace Routes", () => { sort: "discount_rate", sortOrder: "DESC", }), - expect.any(Object), + expect.any(Object) ); }); @@ -200,12 +198,10 @@ describe("Marketplace Routes", () => { it("should handle service errors", async () => { mockMarketplaceService.getPublishedInvoices.mockRejectedValue( - new Error("Database connection failed"), + new Error("Database connection failed") ); - await request(app) - .get("/api/v1/marketplace/invoices") - .expect(500); + await request(app).get("/api/v1/marketplace/invoices").expect(500); }); it("should strip unknown query parameters", async () => { @@ -217,7 +213,7 @@ describe("Marketplace Routes", () => { page: 1, limit: 10, unknownParam: "should-be-stripped", - anotherUnknown: 123 + anotherUnknown: 123, }) .expect(200); @@ -232,7 +228,7 @@ describe("Marketplace Routes", () => { sort: "amount", sortOrder: "DESC", }, - { page: 1, limit: 10 }, + { page: 1, limit: 10 } ); }); @@ -262,8 +258,8 @@ describe("Marketplace Routes", () => { sort: "amount", sortOrder: "DESC", }, - { page: 2, limit: 5 }, + { page: 2, limit: 5 } ); }); }); -}); \ No newline at end of file +}); diff --git a/tests/marketplace.service.test.ts b/tests/marketplace.service.test.ts index 841f8e8..f2cba4b 100644 --- a/tests/marketplace.service.test.ts +++ b/tests/marketplace.service.test.ts @@ -101,7 +101,7 @@ describe("MarketplaceService", () => { sort: "amount", sortOrder: "DESC", }, - { page: 1, limit: 20 }, + { page: 1, limit: 20 } ); }); @@ -133,7 +133,7 @@ describe("MarketplaceService", () => { expect(mockMarketplaceRepository.findPublishedInvoices).toHaveBeenCalledWith( filters, - pagination, + pagination ); }); @@ -148,7 +148,7 @@ describe("MarketplaceService", () => { expect(mockMarketplaceRepository.findPublishedInvoices).toHaveBeenCalledWith( expect.any(Object), - { page: 1, limit: 100 }, // Normalized values + { page: 1, limit: 100 } // Normalized values ); }); @@ -193,4 +193,4 @@ describe("MarketplaceService", () => { expect(result.meta.totalPages).toBe(3); // Math.ceil(25 / 10) }); }); -}); \ No newline at end of file +}); diff --git a/tests/notification.test.ts b/tests/notification.test.ts index 0238e96..aa61a44 100644 --- a/tests/notification.test.ts +++ b/tests/notification.test.ts @@ -60,10 +60,7 @@ function rejectAuthMiddleware() { // avoiding the double-auth problem with createNotificationRouter. // --------------------------------------------------------------------------- -function buildApp( - notificationService: NotificationService, - authUserId?: string, -) { +function buildApp(notificationService: NotificationService, authUserId?: string) { const app = express(); app.use(express.json()); @@ -90,9 +87,7 @@ function buildApp( // Mocked NotificationService // --------------------------------------------------------------------------- -function buildMockService( - overrides: Partial = {}, -): NotificationService { +function buildMockService(overrides: Partial = {}): NotificationService { const defaults = { createNotification: jest.fn(), listNotifications: jest.fn().mockResolvedValue({ @@ -126,7 +121,7 @@ describe("GET /api/v1/notifications", () => { expect(res.body.data).toHaveLength(1); expect(res.body.meta.total).toBe(1); expect(service.listNotifications).toHaveBeenCalledWith( - expect.objectContaining({ userId: "user-1" }), + expect.objectContaining({ userId: "user-1" }) ); }); @@ -137,7 +132,7 @@ describe("GET /api/v1/notifications", () => { await request(app).get("/api/v1/notifications?read=false"); expect(service.listNotifications).toHaveBeenCalledWith( - expect.objectContaining({ read: false }), + expect.objectContaining({ read: false }) ); }); @@ -148,7 +143,7 @@ describe("GET /api/v1/notifications", () => { await request(app).get(`/api/v1/notifications?type=${NotificationType.INVOICE}`); expect(service.listNotifications).toHaveBeenCalledWith( - expect.objectContaining({ type: NotificationType.INVOICE }), + expect.objectContaining({ type: NotificationType.INVOICE }) ); }); @@ -213,4 +208,4 @@ describe("PATCH /api/v1/notifications/:id/read", () => { expect(res.status).toBe(401); }); -}); \ No newline at end of file +}); diff --git a/tests/observability.test.ts b/tests/observability.test.ts index 2f1d5b8..30c49ec 100644 --- a/tests/observability.test.ts +++ b/tests/observability.test.ts @@ -13,7 +13,7 @@ interface LogEntry { class CaptureLogger implements AppLogger { constructor( readonly entries: LogEntry[] = [], - private readonly defaultMetadata: LogMetadata = {}, + private readonly defaultMetadata: LogMetadata = {} ) {} debug(message: string, metadata: LogMetadata = {}): void { @@ -99,12 +99,10 @@ describe("Observability", () => { expect(firstResponse.headers["x-request-id"]).toEqual(expect.any(String)); expect(secondResponse.headers["x-request-id"]).toEqual(expect.any(String)); - expect(firstResponse.headers["x-request-id"]).not.toBe( - secondResponse.headers["x-request-id"], - ); + expect(firstResponse.headers["x-request-id"]).not.toBe(secondResponse.headers["x-request-id"]); const requestLogs = logger.entries.filter( - (entry) => entry.level === "info" && entry.message === "HTTP request completed.", + (entry) => entry.level === "info" && entry.message === "HTTP request completed." ); expect(requestLogs).toHaveLength(2); @@ -112,7 +110,7 @@ describe("Observability", () => { expect.arrayContaining([ firstResponse.headers["x-request-id"], secondResponse.headers["x-request-id"], - ]), + ]) ); }); @@ -134,7 +132,6 @@ describe("Observability", () => { expect(response.body.requestId).toBe("client-request-id"); expect(response.body.data?.requestId).toBe("client-request-id"); - }); it("logs structured auth failure metadata after a 401 response", async () => { @@ -149,7 +146,7 @@ describe("Observability", () => { await request(app).get("/api/v1/auth/me").expect(401); const authFailureLog = logger.entries.find( - (entry) => entry.level === "warn" && entry.message === "API authentication failure.", + (entry) => entry.level === "warn" && entry.message === "API authentication failure." ); expect(authFailureLog).toBeDefined(); @@ -177,23 +174,19 @@ describe("Observability", () => { const metricsResponse = await request(app).get("/metrics").expect(200); expect(metricsResponse.headers["content-type"]).toContain("text/plain"); + expect(metricsResponse.text).toContain("# TYPE stellarsettle_http_requests_total counter"); expect(metricsResponse.text).toContain( - "# TYPE stellarsettle_http_requests_total counter", - ); - expect(metricsResponse.text).toContain( - 'stellarsettle_http_requests_total{method="GET",route="/health",status_class="2xx"} 1', - ); - expect(metricsResponse.text).toContain( - 'stellarsettle_http_requests_total{method="GET",route="/api/v1/auth/me",status_class="4xx"} 1', + 'stellarsettle_http_requests_total{method="GET",route="/health",status_class="2xx"} 1' ); expect(metricsResponse.text).toContain( - 'stellarsettle_http_requests_total{method="GET",route="unmatched",status_class="4xx"} 1', + 'stellarsettle_http_requests_total{method="GET",route="/api/v1/auth/me",status_class="4xx"} 1' ); expect(metricsResponse.text).toContain( - "# TYPE stellarsettle_http_request_duration_ms histogram", + 'stellarsettle_http_requests_total{method="GET",route="unmatched",status_class="4xx"} 1' ); expect(metricsResponse.text).toContain( - "# TYPE stellarsettle_process_uptime_seconds gauge", + "# TYPE stellarsettle_http_request_duration_ms histogram" ); + expect(metricsResponse.text).toContain("# TYPE stellarsettle_process_uptime_seconds gauge"); }); }); diff --git a/tests/orchestrate-investment-funding.logging.test.ts b/tests/orchestrate-investment-funding.logging.test.ts index 075a5d1..c3a1250 100644 --- a/tests/orchestrate-investment-funding.logging.test.ts +++ b/tests/orchestrate-investment-funding.logging.test.ts @@ -1,9 +1,7 @@ import crypto from "crypto"; import { Investment } from "../src/models/Investment.model"; import { Transaction } from "../src/models/Transaction.model"; -import { - OrchestrateInvestmentFundingService, -} from "../src/services/stellar/orchestrate-investment-funding.service"; +import { OrchestrateInvestmentFundingService } from "../src/services/stellar/orchestrate-investment-funding.service"; import { InvestmentStatus, TransactionStatus, TransactionType } from "../src/types/enums"; import type { AppLogger } from "../src/observability/logger"; @@ -100,7 +98,7 @@ describe("OrchestrateInvestmentFundingService structured escrow logging", () => function_name: "prepare_investment_funding", invoice_id: investment.invoiceId, submitted_at: expect.any(String), - }), + }) ); expect(logger.info).toHaveBeenCalledWith( @@ -112,7 +110,7 @@ describe("OrchestrateInvestmentFundingService structured escrow logging", () => tx_hash: "escrow-tx-hash", ledger: 555111, confirmed_at: expect.any(String), - }), + }) ); const [, debugMetadata] = logger.debug.mock.calls[0]; @@ -148,7 +146,7 @@ describe("OrchestrateInvestmentFundingService structured escrow logging", () => invoice_id: investment.invoiceId, submitted_at: expect.any(String), error_reason: "RPC unavailable", - }), + }) ); expect(logger.info).not.toHaveBeenCalled(); }); diff --git a/tests/orchestrate-investment-funding.service.test.ts b/tests/orchestrate-investment-funding.service.test.ts index 2273895..9ba6a6f 100644 --- a/tests/orchestrate-investment-funding.service.test.ts +++ b/tests/orchestrate-investment-funding.service.test.ts @@ -1,9 +1,7 @@ import crypto from "crypto"; import { Investment } from "../src/models/Investment.model"; import { Transaction } from "../src/models/Transaction.model"; -import { - OrchestrateInvestmentFundingService, -} from "../src/services/stellar/orchestrate-investment-funding.service"; +import { OrchestrateInvestmentFundingService } from "../src/services/stellar/orchestrate-investment-funding.service"; import { InvestmentStatus, TransactionStatus, TransactionType } from "../src/types/enums"; import { ServiceError } from "../src/utils/service-error"; @@ -147,13 +145,13 @@ describe("OrchestrateInvestmentFundingService", () => { findTransactionByInvestmentIdForUpdate: async () => null, saveTransaction, createTransaction: (input) => createTransaction(input), - }), + }) ), }, sorobanEscrowClient: { - prepareInvestmentFunding: jest.fn().mockRejectedValue( - new ServiceError("soroban_unavailable", "RPC unavailable", 503), - ), + prepareInvestmentFunding: jest + .fn() + .mockRejectedValue(new ServiceError("soroban_unavailable", "RPC unavailable", 503)), }, config: { enabled: true, diff --git a/tests/rate-limit-wallet.test.ts b/tests/rate-limit-wallet.test.ts index 84c3184..3167cdd 100644 --- a/tests/rate-limit-wallet.test.ts +++ b/tests/rate-limit-wallet.test.ts @@ -1,325 +1,341 @@ import request from "supertest"; import express from "express"; import jwt from "jsonwebtoken"; -import { createWalletRateLimiter, resetRateLimitStores } from "../src/middleware/rate-limit-wallet.middleware"; +import { + createWalletRateLimiter, + resetRateLimitStores, +} from "../src/middleware/rate-limit-wallet.middleware"; import { createErrorMiddleware } from "../src/middleware/error.middleware"; import { logger } from "../src/observability/logger"; import { KYCStatus, UserType } from "../src/types/enums"; describe("Wallet-based rate limiting", () => { - const TEST_SECRET = "test-secret-rate-limit"; - const WALLET_A = "GAWalletA123456789012345678901234567890123456789012345"; - const WALLET_B = "GBWalletB123456789012345678901234567890123456789012345"; - - function createToken(walletAddress: string): string { - return jwt.sign( - { sub: walletAddress, stellarAddress: walletAddress }, - TEST_SECRET, - ); - } - - let app: express.Application; - - beforeEach(() => { - resetRateLimitStores(); - - process.env.JWT_SECRET = TEST_SECRET; - - app = express(); - app.use(express.json()); - - // Create a test endpoint with wallet rate limiter (max 3 per 60s) - const testRateLimiter = createWalletRateLimiter( - { windowMs: 60_000, maxRequests: 3 }, - "test-endpoint", - ); - - app.post( - "/api/v1/test-rate-limit", - (req, res, next) => { - const authHeader = req.headers.authorization; - if (!authHeader?.startsWith("Bearer ")) { - res.status(401).json({ error: "Unauthorized" }); - return; - } - const token = authHeader.slice(7); - try { - const payload = jwt.verify(token, TEST_SECRET) as any; - (req as any).user = { - id: payload.sub, - stellarAddress: payload.stellarAddress, - email: null, - userType: UserType.INVESTOR, - kycStatus: KYCStatus.APPROVED, - createdAt: new Date(), - updatedAt: new Date(), - }; - next(); - } catch { - res.status(401).json({ error: "Invalid token" }); - } - }, - testRateLimiter, - (_req, res) => { - res.status(200).json({ success: true }); - }, - ); - - app.use(createErrorMiddleware(logger)); - }); - - afterEach(() => { - delete process.env.JWT_SECRET; - }); + const TEST_SECRET = "test-secret-rate-limit"; + const WALLET_A = "GAWalletA123456789012345678901234567890123456789012345"; + const WALLET_B = "GBWalletB123456789012345678901234567890123456789012345"; - it("should allow requests up to the limit", async () => { - const tokenA = createToken(WALLET_A); + function createToken(walletAddress: string): string { + return jwt.sign({ sub: walletAddress, stellarAddress: walletAddress }, TEST_SECRET); + } - // First 3 requests should succeed - for (let i = 0; i < 3; i++) { - await request(app) - .post("/api/v1/test-rate-limit") - .set("Authorization", `Bearer ${tokenA}`) - .expect(200); - } - }); + let app: express.Application; - it("should return 429 after exceeding the limit", async () => { - const tokenA = createToken(WALLET_A); + beforeEach(() => { + resetRateLimitStores(); - // Exhaust the 3 request limit - for (let i = 0; i < 3; i++) { - await request(app) - .post("/api/v1/test-rate-limit") - .set("Authorization", `Bearer ${tokenA}`) - .expect(200); - } + process.env.JWT_SECRET = TEST_SECRET; - // 4th request should be rate limited - const response = await request(app) - .post("/api/v1/test-rate-limit") - .set("Authorization", `Bearer ${tokenA}`) - .expect(429); - - expect(response.body).toMatchObject({ - success: false, - error: { - code: "RATE_LIMIT_EXCEEDED", - }, - }); - }); + app = express(); + app.use(express.json()); - it("should include Retry-After header in 429 response", async () => { - const tokenA = createToken(WALLET_A); + // Create a test endpoint with wallet rate limiter (max 3 per 60s) + const testRateLimiter = createWalletRateLimiter( + { windowMs: 60_000, maxRequests: 3 }, + "test-endpoint" + ); - // Exhaust the limit - for (let i = 0; i < 3; i++) { - await request(app) - .post("/api/v1/test-rate-limit") - .set("Authorization", `Bearer ${tokenA}`) - .expect(200); + app.post( + "/api/v1/test-rate-limit", + (req, res, next) => { + const authHeader = req.headers.authorization; + if (!authHeader?.startsWith("Bearer ")) { + res.status(401).json({ error: "Unauthorized" }); + return; + } + const token = authHeader.slice(7); + try { + const payload = jwt.verify(token, TEST_SECRET) as any; + (req as any).user = { + id: payload.sub, + stellarAddress: payload.stellarAddress, + email: null, + userType: UserType.INVESTOR, + kycStatus: KYCStatus.APPROVED, + createdAt: new Date(), + updatedAt: new Date(), + }; + next(); + } catch { + res.status(401).json({ error: "Invalid token" }); } + }, + testRateLimiter, + (_req, res) => { + res.status(200).json({ success: true }); + } + ); + + app.use(createErrorMiddleware(logger)); + }); + + afterEach(() => { + delete process.env.JWT_SECRET; + }); + + it("should allow requests up to the limit", async () => { + const tokenA = createToken(WALLET_A); + + // First 3 requests should succeed + for (let i = 0; i < 3; i++) { + await request(app) + .post("/api/v1/test-rate-limit") + .set("Authorization", `Bearer ${tokenA}`) + .expect(200); + } + }); + + it("should return 429 after exceeding the limit", async () => { + const tokenA = createToken(WALLET_A); - const response = await request(app) - .post("/api/v1/test-rate-limit") - .set("Authorization", `Bearer ${tokenA}`) - .expect(429); + // Exhaust the 3 request limit + for (let i = 0; i < 3; i++) { + await request(app) + .post("/api/v1/test-rate-limit") + .set("Authorization", `Bearer ${tokenA}`) + .expect(200); + } - expect(response.headers).toHaveProperty("retry-after"); - const retryAfter = parseInt(response.headers["retry-after"], 10); - expect(retryAfter).toBeGreaterThanOrEqual(1); - expect(retryAfter).toBeLessThanOrEqual(60); + // 4th request should be rate limited + const response = await request(app) + .post("/api/v1/test-rate-limit") + .set("Authorization", `Bearer ${tokenA}`) + .expect(429); + + expect(response.body).toMatchObject({ + success: false, + error: { + code: "RATE_LIMIT_EXCEEDED", + }, }); + }); - it("should not affect wallet B when wallet A is rate limited", async () => { - const tokenA = createToken(WALLET_A); - const tokenB = createToken(WALLET_B); + it("should include Retry-After header in 429 response", async () => { + const tokenA = createToken(WALLET_A); - // Exhaust wallet A's limit - for (let i = 0; i < 3; i++) { - await request(app) - .post("/api/v1/test-rate-limit") - .set("Authorization", `Bearer ${tokenA}`) - .expect(200); - } + // Exhaust the limit + for (let i = 0; i < 3; i++) { + await request(app) + .post("/api/v1/test-rate-limit") + .set("Authorization", `Bearer ${tokenA}`) + .expect(200); + } - // Wallet A should be rate limited - await request(app) - .post("/api/v1/test-rate-limit") - .set("Authorization", `Bearer ${tokenA}`) - .expect(429); - - // Wallet B should still be allowed - await request(app) - .post("/api/v1/test-rate-limit") - .set("Authorization", `Bearer ${tokenB}`) - .expect(200); - }); + const response = await request(app) + .post("/api/v1/test-rate-limit") + .set("Authorization", `Bearer ${tokenA}`) + .expect(429); + + expect(response.headers).toHaveProperty("retry-after"); + const retryAfter = parseInt(response.headers["retry-after"], 10); + expect(retryAfter).toBeGreaterThanOrEqual(1); + expect(retryAfter).toBeLessThanOrEqual(60); + }); + + it("should not affect wallet B when wallet A is rate limited", async () => { + const tokenA = createToken(WALLET_A); + const tokenB = createToken(WALLET_B); + + // Exhaust wallet A's limit + for (let i = 0; i < 3; i++) { + await request(app) + .post("/api/v1/test-rate-limit") + .set("Authorization", `Bearer ${tokenA}`) + .expect(200); + } - it("should allow requests again after the window resets", async () => { - // Use a very short window for testing - resetRateLimitStores(); - - const shortWindowApp = express(); - shortWindowApp.use(express.json()); - - const shortWindowLimiter = createWalletRateLimiter( - { windowMs: 100, maxRequests: 1 }, // 100ms window, 1 request max - "short-window-test", - ); - - shortWindowApp.post( - "/api/v1/short-window", - (req, res, next) => { - const authHeader = req.headers.authorization; - if (!authHeader?.startsWith("Bearer ")) { - res.status(401).json({ error: "Unauthorized" }); - return; - } - const token = authHeader.slice(7); - try { - const payload = jwt.verify(token, TEST_SECRET) as any; - (req as any).user = { - id: payload.sub, - stellarAddress: payload.stellarAddress, - email: null, - userType: UserType.INVESTOR, - kycStatus: KYCStatus.APPROVED, - createdAt: new Date(), - updatedAt: new Date(), - }; - next(); - } catch { - res.status(401).json({ error: "Invalid token" }); - } - }, - shortWindowLimiter, - (_req, res) => { - res.status(200).json({ success: true }); - }, - ); - - shortWindowApp.use(createErrorMiddleware(logger)); - - const tokenA = createToken(WALLET_A); - - // First request should succeed - await request(shortWindowApp) - .post("/api/v1/short-window") - .set("Authorization", `Bearer ${tokenA}`) - .expect(200); - - // Second request should be rate limited - await request(shortWindowApp) - .post("/api/v1/short-window") - .set("Authorization", `Bearer ${tokenA}`) - .expect(429); - - // Wait for window to reset - await new Promise((resolve) => setTimeout(resolve, 150)); - - // After window reset, requests should succeed again - await request(shortWindowApp) - .post("/api/v1/short-window") - .set("Authorization", `Bearer ${tokenA}`) - .expect(200); - }); + // Wallet A should be rate limited + await request(app) + .post("/api/v1/test-rate-limit") + .set("Authorization", `Bearer ${tokenA}`) + .expect(429); + + // Wallet B should still be allowed + await request(app) + .post("/api/v1/test-rate-limit") + .set("Authorization", `Bearer ${tokenB}`) + .expect(200); + }); + + it("should allow requests again after the window resets", async () => { + // Use a very short window for testing + resetRateLimitStores(); + + const shortWindowApp = express(); + shortWindowApp.use(express.json()); + + const shortWindowLimiter = createWalletRateLimiter( + { windowMs: 100, maxRequests: 1 }, // 100ms window, 1 request max + "short-window-test" + ); + + shortWindowApp.post( + "/api/v1/short-window", + (req, res, next) => { + const authHeader = req.headers.authorization; + if (!authHeader?.startsWith("Bearer ")) { + res.status(401).json({ error: "Unauthorized" }); + return; + } + const token = authHeader.slice(7); + try { + const payload = jwt.verify(token, TEST_SECRET) as any; + (req as any).user = { + id: payload.sub, + stellarAddress: payload.stellarAddress, + email: null, + userType: UserType.INVESTOR, + kycStatus: KYCStatus.APPROVED, + createdAt: new Date(), + updatedAt: new Date(), + }; + next(); + } catch { + res.status(401).json({ error: "Invalid token" }); + } + }, + shortWindowLimiter, + (_req, res) => { + res.status(200).json({ success: true }); + } + ); + + shortWindowApp.use(createErrorMiddleware(logger)); + + const tokenA = createToken(WALLET_A); + + // First request should succeed + await request(shortWindowApp) + .post("/api/v1/short-window") + .set("Authorization", `Bearer ${tokenA}`) + .expect(200); + + // Second request should be rate limited + await request(shortWindowApp) + .post("/api/v1/short-window") + .set("Authorization", `Bearer ${tokenA}`) + .expect(429); + + // Wait for window to reset + await new Promise((resolve) => setTimeout(resolve, 150)); + + // After window reset, requests should succeed again + await request(shortWindowApp) + .post("/api/v1/short-window") + .set("Authorization", `Bearer ${tokenA}`) + .expect(200); + }); + + it("should return 401 if no wallet address in request", async () => { + // Send request without auth + await request(app).post("/api/v1/test-rate-limit").expect(401); + }); + + it("should reset counter after window expires and allow full quota again", async () => { + resetRateLimitStores(); + + const shortApp = express(); + shortApp.use(express.json()); + + const limiter = createWalletRateLimiter({ windowMs: 150, maxRequests: 3 }, "reset-test"); + + shortApp.post( + "/test", + (req, res, next) => { + const authHeader = req.headers.authorization; + if (!authHeader?.startsWith("Bearer ")) { + res.status(401).json({ error: "Unauthorized" }); + return; + } + const token = authHeader.slice(7); + try { + const payload = jwt.verify(token, TEST_SECRET) as any; + (req as any).user = { id: payload.sub, stellarAddress: payload.stellarAddress }; + next(); + } catch { + res.status(401).json({ error: "Invalid token" }); + } + }, + limiter, + (_req, res) => { + res.status(200).json({ success: true }); + } + ); - it("should return 401 if no wallet address in request", async () => { - // Send request without auth - await request(app) - .post("/api/v1/test-rate-limit") - .expect(401); - }); + shortApp.use(createErrorMiddleware(logger)); - it("should reset counter after window expires and allow full quota again", async () => { - resetRateLimitStores(); + const token = createToken(WALLET_A); - const shortApp = express(); - shortApp.use(express.json()); + // Exhaust the limit (3 requests) + for (let i = 0; i < 3; i++) { + await request(shortApp).post("/test").set("Authorization", `Bearer ${token}`).expect(200); + } - const limiter = createWalletRateLimiter( - { windowMs: 150, maxRequests: 3 }, - "reset-test", - ); + // 4th request should be rate limited + await request(shortApp).post("/test").set("Authorization", `Bearer ${token}`).expect(429); - shortApp.post("/test", (req, res, next) => { - const authHeader = req.headers.authorization; - if (!authHeader?.startsWith("Bearer ")) { res.status(401).json({ error: "Unauthorized" }); return; } - const token = authHeader.slice(7); - try { - const payload = jwt.verify(token, TEST_SECRET) as any; - (req as any).user = { id: payload.sub, stellarAddress: payload.stellarAddress }; - next(); - } catch { res.status(401).json({ error: "Invalid token" }); } - }, limiter, (_req, res) => { res.status(200).json({ success: true }); }); + // Wait for window to expire + await new Promise((resolve) => setTimeout(resolve, 200)); - shortApp.use(createErrorMiddleware(logger)); + // Counter should have reset — 3 more requests should succeed + for (let i = 0; i < 3; i++) { + await request(shortApp).post("/test").set("Authorization", `Bearer ${token}`).expect(200); + } - const token = createToken(WALLET_A); + // 4th request after reset should be rate limited again + await request(shortApp).post("/test").set("Authorization", `Bearer ${token}`).expect(429); + }); - // Exhaust the limit (3 requests) - for (let i = 0; i < 3; i++) { - await request(shortApp).post("/test").set("Authorization", `Bearer ${token}`).expect(200); - } + it("should reset per wallet, not globally", async () => { + resetRateLimitStores(); - // 4th request should be rate limited - await request(shortApp).post("/test").set("Authorization", `Bearer ${token}`).expect(429); + const shortApp = express(); + shortApp.use(express.json()); - // Wait for window to expire - await new Promise((resolve) => setTimeout(resolve, 200)); + const limiter = createWalletRateLimiter({ windowMs: 150, maxRequests: 2 }, "per-wallet-test"); - // Counter should have reset — 3 more requests should succeed - for (let i = 0; i < 3; i++) { - await request(shortApp).post("/test").set("Authorization", `Bearer ${token}`).expect(200); + shortApp.post( + "/test", + (req, res, next) => { + const authHeader = req.headers.authorization; + if (!authHeader?.startsWith("Bearer ")) { + res.status(401).json({ error: "Unauthorized" }); + return; } - - // 4th request after reset should be rate limited again - await request(shortApp).post("/test").set("Authorization", `Bearer ${token}`).expect(429); - }); - - it("should reset per wallet, not globally", async () => { - resetRateLimitStores(); - - const shortApp = express(); - shortApp.use(express.json()); - - const limiter = createWalletRateLimiter( - { windowMs: 150, maxRequests: 2 }, - "per-wallet-test", - ); - - shortApp.post("/test", (req, res, next) => { - const authHeader = req.headers.authorization; - if (!authHeader?.startsWith("Bearer ")) { res.status(401).json({ error: "Unauthorized" }); return; } - const token = authHeader.slice(7); - try { - const payload = jwt.verify(token, TEST_SECRET) as any; - (req as any).user = { id: payload.sub, stellarAddress: payload.stellarAddress }; - next(); - } catch { res.status(401).json({ error: "Invalid token" }); } - }, limiter, (_req, res) => { res.status(200).json({ success: true }); }); - - shortApp.use(createErrorMiddleware(logger)); - - const tokenA = createToken(WALLET_A); - const tokenB = createToken(WALLET_B); - - // Exhaust wallet A - await request(shortApp).post("/test").set("Authorization", `Bearer ${tokenA}`).expect(200); - await request(shortApp).post("/test").set("Authorization", `Bearer ${tokenA}`).expect(200); - await request(shortApp).post("/test").set("Authorization", `Bearer ${tokenA}`).expect(429); - - // Wallet B should still have full quota - await request(shortApp).post("/test").set("Authorization", `Bearer ${tokenB}`).expect(200); - await request(shortApp).post("/test").set("Authorization", `Bearer ${tokenB}`).expect(200); - await request(shortApp).post("/test").set("Authorization", `Bearer ${tokenB}`).expect(429); - - // Wait for window to expire - await new Promise((resolve) => setTimeout(resolve, 200)); - - // Both wallets should have fresh quotas - await request(shortApp).post("/test").set("Authorization", `Bearer ${tokenA}`).expect(200); - await request(shortApp).post("/test").set("Authorization", `Bearer ${tokenB}`).expect(200); - }); -}); \ No newline at end of file + const token = authHeader.slice(7); + try { + const payload = jwt.verify(token, TEST_SECRET) as any; + (req as any).user = { id: payload.sub, stellarAddress: payload.stellarAddress }; + next(); + } catch { + res.status(401).json({ error: "Invalid token" }); + } + }, + limiter, + (_req, res) => { + res.status(200).json({ success: true }); + } + ); + + shortApp.use(createErrorMiddleware(logger)); + + const tokenA = createToken(WALLET_A); + const tokenB = createToken(WALLET_B); + + // Exhaust wallet A + await request(shortApp).post("/test").set("Authorization", `Bearer ${tokenA}`).expect(200); + await request(shortApp).post("/test").set("Authorization", `Bearer ${tokenA}`).expect(200); + await request(shortApp).post("/test").set("Authorization", `Bearer ${tokenA}`).expect(429); + + // Wallet B should still have full quota + await request(shortApp).post("/test").set("Authorization", `Bearer ${tokenB}`).expect(200); + await request(shortApp).post("/test").set("Authorization", `Bearer ${tokenB}`).expect(200); + await request(shortApp).post("/test").set("Authorization", `Bearer ${tokenB}`).expect(429); + + // Wait for window to expire + await new Promise((resolve) => setTimeout(resolve, 200)); + + // Both wallets should have fresh quotas + await request(shortApp).post("/test").set("Authorization", `Bearer ${tokenA}`).expect(200); + await request(shortApp).post("/test").set("Authorization", `Bearer ${tokenB}`).expect(200); + }); +}); diff --git a/tests/reconcile-pending-stellar-state.worker.test.ts b/tests/reconcile-pending-stellar-state.worker.test.ts index 50a827b..fbe12ad 100644 --- a/tests/reconcile-pending-stellar-state.worker.test.ts +++ b/tests/reconcile-pending-stellar-state.worker.test.ts @@ -16,7 +16,7 @@ interface LogEntry { class CaptureLogger implements AppLogger { constructor( readonly entries: LogEntry[] = [], - private readonly defaultMetadata: LogMetadata = {}, + private readonly defaultMetadata: LogMetadata = {} ) {} debug(message: string, metadata: LogMetadata = {}): void { @@ -74,7 +74,7 @@ class CaptureLogger implements AppLogger { function createCandidate( investmentId: string, stellarTxHash: string, - overrides: Partial = {}, + overrides: Partial = {} ): ReconciliationCandidate { return { investmentId, @@ -87,7 +87,7 @@ function createCandidate( function createVerifiedResult( investmentId: string, - outcome: "verified" | "already_verified", + outcome: "verified" | "already_verified" ): PaymentVerificationResult { return { outcome, @@ -107,22 +107,22 @@ describe("ReconcilePendingStellarStateWorker", () => { it("reconciles actionable candidates, continues after errors, and yields between items", async () => { const now = new Date("2026-01-01T00:10:00.000Z"); const repository = { - findPendingCandidates: jest.fn().mockResolvedValue([ - createCandidate("investment-1", "hash-1"), - createCandidate("investment-2", "hash-2"), - createCandidate("investment-3", "hash-3"), - ]), + findPendingCandidates: jest + .fn() + .mockResolvedValue([ + createCandidate("investment-1", "hash-1"), + createCandidate("investment-2", "hash-2"), + createCandidate("investment-3", "hash-3"), + ]), }; const paymentVerifier = { verifyPayment: jest .fn() .mockResolvedValueOnce(createVerifiedResult("investment-1", "verified")) .mockRejectedValueOnce( - new ServiceError("transaction_not_found", "Transaction not found.", 404), + new ServiceError("transaction_not_found", "Transaction not found.", 404) ) - .mockResolvedValueOnce( - createVerifiedResult("investment-3", "already_verified"), - ), + .mockResolvedValueOnce(createVerifiedResult("investment-3", "already_verified")), }; const yieldControl = jest.fn(async () => undefined); const logger = new CaptureLogger(); @@ -145,7 +145,7 @@ describe("ReconcilePendingStellarStateWorker", () => { expect(repository.findPendingCandidates).toHaveBeenCalledWith( new Date("2026-01-01T00:09:00.000Z"), - 3, + 3 ); expect(paymentVerifier.verifyPayment).toHaveBeenCalledTimes(3); expect(yieldControl).toHaveBeenCalledTimes(3); @@ -167,17 +167,19 @@ describe("ReconcilePendingStellarStateWorker", () => { level: "debug", message: "Completed Stellar reconciliation tick.", }), - ]), + ]) ); }); it("logs cycle start and completion once per cycle with matching cycle_id", async () => { const now = new Date("2026-01-01T00:10:00.000Z"); const repository = { - findPendingCandidates: jest.fn().mockResolvedValue([ - createCandidate("investment-1", "hash-1"), - createCandidate("investment-2", "hash-2"), - ]), + findPendingCandidates: jest + .fn() + .mockResolvedValue([ + createCandidate("investment-1", "hash-1"), + createCandidate("investment-2", "hash-2"), + ]), }; const paymentVerifier = { verifyPayment: jest @@ -204,10 +206,11 @@ describe("ReconcilePendingStellarStateWorker", () => { await worker.runTick(); const startLogs = logger.entries.filter( - (entry) => entry.level === "info" && entry.message === "Started Stellar reconciliation tick.", + (entry) => entry.level === "info" && entry.message === "Started Stellar reconciliation tick." ); const completionLogs = logger.entries.filter( - (entry) => entry.level === "debug" && entry.message === "Completed Stellar reconciliation tick.", + (entry) => + entry.level === "debug" && entry.message === "Completed Stellar reconciliation tick." ); expect(startLogs).toHaveLength(1); @@ -231,11 +234,13 @@ describe("ReconcilePendingStellarStateWorker", () => { it("stops starting new reconciliations once the tick runtime budget is exhausted", async () => { let currentTimeMs = Date.parse("2026-01-01T00:00:00.000Z"); const repository = { - findPendingCandidates: jest.fn().mockResolvedValue([ - createCandidate("investment-1", "hash-1"), - createCandidate("investment-2", "hash-2"), - createCandidate("investment-3", "hash-3"), - ]), + findPendingCandidates: jest + .fn() + .mockResolvedValue([ + createCandidate("investment-1", "hash-1"), + createCandidate("investment-2", "hash-2"), + createCandidate("investment-3", "hash-3"), + ]), }; const paymentVerifier = { verifyPayment: jest.fn(async (input: { investmentId: string }) => { @@ -359,7 +364,7 @@ describe("ReconcilePendingStellarStateWorker", () => { expect(repository.findPendingCandidates).toHaveBeenCalledTimes(1); expect(repository.findPendingCandidates).toHaveBeenCalledWith( new Date("2026-01-01T00:09:00.000Z"), - 10, + 10 ); // Pending investment was verified @@ -372,7 +377,8 @@ describe("ReconcilePendingStellarStateWorker", () => { // it is never touched during reconciliation. // Log should show 1 checked, 0 skipped (only 1 pending candidate existed) const completionLog = logger.entries.find( - (entry: LogEntry) => entry.level === "debug" && entry.message === "Completed Stellar reconciliation tick.", + (entry: LogEntry) => + entry.level === "debug" && entry.message === "Completed Stellar reconciliation tick." ); expect(completionLog).toBeDefined(); expect(completionLog?.metadata).toMatchObject({ @@ -386,11 +392,13 @@ describe("ReconcilePendingStellarStateWorker", () => { const logger = new CaptureLogger(); const repository = { - findPendingCandidates: jest.fn().mockResolvedValue([ - createCandidate("investment-1", "hash-1"), - createCandidate("investment-2", "hash-2"), - createCandidate("investment-3", "hash-3"), - ]), + findPendingCandidates: jest + .fn() + .mockResolvedValue([ + createCandidate("investment-1", "hash-1"), + createCandidate("investment-2", "hash-2"), + createCandidate("investment-3", "hash-3"), + ]), }; const paymentVerifier = { @@ -424,7 +432,8 @@ describe("ReconcilePendingStellarStateWorker", () => { expect(result.failed).toBe(0); const completionLog = logger.entries.find( - (entry: LogEntry) => entry.level === "debug" && entry.message === "Completed Stellar reconciliation tick.", + (entry: LogEntry) => + entry.level === "debug" && entry.message === "Completed Stellar reconciliation tick." ); expect(completionLog).toBeDefined(); expect(completionLog?.metadata).toMatchObject({ diff --git a/tests/settlement-completion-log.test.ts b/tests/settlement-completion-log.test.ts index 89e63ac..3362df8 100644 --- a/tests/settlement-completion-log.test.ts +++ b/tests/settlement-completion-log.test.ts @@ -29,7 +29,7 @@ describe("logSettlementCompletion", () => { total_proceeds: "12345.0000000", investor_count: 3, settled_at: expect.any(String), - }), + }) ); }); diff --git a/tests/unit/auth-failure.test.ts b/tests/unit/auth-failure.test.ts index 4e1f1fb..66e2171 100644 --- a/tests/unit/auth-failure.test.ts +++ b/tests/unit/auth-failure.test.ts @@ -1,8 +1,5 @@ import jwt from "jsonwebtoken"; -import { - buildAuthFailureDetails, - truncateWalletAddress, -} from "../../src/lib/auth-failure"; +import { buildAuthFailureDetails, truncateWalletAddress } from "../../src/lib/auth-failure"; describe("auth failure helpers", () => { it("truncates wallet addresses consistently", () => { @@ -12,11 +9,9 @@ describe("auth failure helpers", () => { }); it("extracts a truncated address from a parseable token", () => { - const token = jwt.sign( - { sub: "GABCDEFGHIJKLMNO1234567890" }, - "test-secret", - { expiresIn: "1h" }, - ); + const token = jwt.sign({ sub: "GABCDEFGHIJKLMNO1234567890" }, "test-secret", { + expiresIn: "1h", + }); expect(buildAuthFailureDetails(token, "invalid_signature")).toEqual({ authFailure: { diff --git a/tests/unit/cursor-pagination.test.ts b/tests/unit/cursor-pagination.test.ts index 33f12e0..b918dcb 100644 --- a/tests/unit/cursor-pagination.test.ts +++ b/tests/unit/cursor-pagination.test.ts @@ -1,91 +1,91 @@ import { encodeCursor, decodeCursor } from "../../src/utils/cursor-pagination.utils"; describe("encodeCursor / decodeCursor", () => { - it("encodes and decodes a cursor correctly", () => { - const date = new Date("2026-07-28T15:00:00.000Z"); - const id = "abc-123-def"; + it("encodes and decodes a cursor correctly", () => { + const date = new Date("2026-07-28T15:00:00.000Z"); + const id = "abc-123-def"; - const cursor = encodeCursor(date, id); - const decoded = decodeCursor(cursor); + const cursor = encodeCursor(date, id); + const decoded = decodeCursor(cursor); - expect(decoded.createdAt.toISOString()).toBe(date.toISOString()); - expect(decoded.id).toBe(id); - }); + expect(decoded.createdAt.toISOString()).toBe(date.toISOString()); + expect(decoded.id).toBe(id); + }); - it("produces a valid base64 string", () => { - const date = new Date(); - const id = "some-uuid-here"; - const cursor = encodeCursor(date, id); + it("produces a valid base64 string", () => { + const date = new Date(); + const id = "some-uuid-here"; + const cursor = encodeCursor(date, id); - // Should be a non-empty base64 string - expect(cursor).toBeTruthy(); - expect(typeof cursor).toBe("string"); + // Should be a non-empty base64 string + expect(cursor).toBeTruthy(); + expect(typeof cursor).toBe("string"); - // Should be decodable by standard base64 - const decoded = Buffer.from(cursor, "base64").toString("utf-8"); - expect(decoded).toContain("::"); - }); + // Should be decodable by standard base64 + const decoded = Buffer.from(cursor, "base64").toString("utf-8"); + expect(decoded).toContain("::"); + }); - it("handles UUIDs with hyphens and numbers", () => { - const date = new Date("2026-01-01T00:00:00.000Z"); - const id = "550e8400-e29b-41d4-a716-446655440000"; + it("handles UUIDs with hyphens and numbers", () => { + const date = new Date("2026-01-01T00:00:00.000Z"); + const id = "550e8400-e29b-41d4-a716-446655440000"; - const cursor = encodeCursor(date, id); - const decoded = decodeCursor(cursor); + const cursor = encodeCursor(date, id); + const decoded = decodeCursor(cursor); - expect(decoded.createdAt.toISOString()).toBe("2026-01-01T00:00:00.000Z"); - expect(decoded.id).toBe(id); - }); + expect(decoded.createdAt.toISOString()).toBe("2026-01-01T00:00:00.000Z"); + expect(decoded.id).toBe(id); + }); - it("handles dates with timezone offsets correctly", () => { - // Date with +05:30 offset - const date = new Date("2026-07-28T20:30:00.000+05:30"); - const id = "test-id"; + it("handles dates with timezone offsets correctly", () => { + // Date with +05:30 offset + const date = new Date("2026-07-28T20:30:00.000+05:30"); + const id = "test-id"; - const cursor = encodeCursor(date, id); - const decoded = decodeCursor(cursor); + const cursor = encodeCursor(date, id); + const decoded = decodeCursor(cursor); - // Should normalize to UTC - expect(decoded.createdAt.toISOString()).toBe("2026-07-28T15:00:00.000Z"); - expect(decoded.id).toBe(id); - }); + // Should normalize to UTC + expect(decoded.createdAt.toISOString()).toBe("2026-07-28T15:00:00.000Z"); + expect(decoded.id).toBe(id); + }); - it("throws on invalid cursor format (no separator)", () => { - const invalidCursor = Buffer.from("just-a-string-without-separator").toString("base64"); + it("throws on invalid cursor format (no separator)", () => { + const invalidCursor = Buffer.from("just-a-string-without-separator").toString("base64"); - expect(() => decodeCursor(invalidCursor)).toThrow("Invalid cursor format"); - }); + expect(() => decodeCursor(invalidCursor)).toThrow("Invalid cursor format"); + }); - it("throws on cursor with empty date component", () => { - const invalidCursor = Buffer.from("::some-id").toString("base64"); + it("throws on cursor with empty date component", () => { + const invalidCursor = Buffer.from("::some-id").toString("base64"); - expect(() => decodeCursor(invalidCursor)).toThrow("Invalid cursor format"); - }); + expect(() => decodeCursor(invalidCursor)).toThrow("Invalid cursor format"); + }); - it("throws on cursor with empty id component", () => { - const invalidCursor = Buffer.from("2026-07-28T15:00:00.000Z::").toString("base64"); + it("throws on cursor with empty id component", () => { + const invalidCursor = Buffer.from("2026-07-28T15:00:00.000Z::").toString("base64"); - expect(() => decodeCursor(invalidCursor)).toThrow("Invalid cursor format"); - }); + expect(() => decodeCursor(invalidCursor)).toThrow("Invalid cursor format"); + }); - it("throws on cursor with unparseable date", () => { - const invalidCursor = Buffer.from("not-a-date::some-id").toString("base64"); + it("throws on cursor with unparseable date", () => { + const invalidCursor = Buffer.from("not-a-date::some-id").toString("base64"); - expect(() => decodeCursor(invalidCursor)).toThrow("Invalid cursor format"); - }); + expect(() => decodeCursor(invalidCursor)).toThrow("Invalid cursor format"); + }); - it("throws on completely invalid base64 string", () => { - expect(() => decodeCursor("!!!not-valid-base64!!!")).toThrow(); - }); + it("throws on completely invalid base64 string", () => { + expect(() => decodeCursor("!!!not-valid-base64!!!")).toThrow(); + }); - it("supports ids containing pipe characters (:: is the separator)", () => { - const date = new Date("2026-07-28T15:00:00.000Z"); - const id = "pipe|in|id"; + it("supports ids containing pipe characters (:: is the separator)", () => { + const date = new Date("2026-07-28T15:00:00.000Z"); + const id = "pipe|in|id"; - const cursor = encodeCursor(date, id); - const decoded = decodeCursor(cursor); + const cursor = encodeCursor(date, id); + const decoded = decodeCursor(cursor); - expect(decoded.createdAt.toISOString()).toBe(date.toISOString()); - expect(decoded.id).toBe(id); - }); -}); \ No newline at end of file + expect(decoded.createdAt.toISOString()).toBe(date.toISOString()); + expect(decoded.id).toBe(id); + }); +}); diff --git a/tests/unit/extract-wallet-from-token.test.ts b/tests/unit/extract-wallet-from-token.test.ts index 6811999..7f982d6 100644 --- a/tests/unit/extract-wallet-from-token.test.ts +++ b/tests/unit/extract-wallet-from-token.test.ts @@ -53,7 +53,9 @@ describe("extractWalletFromToken", () => { }); it("returns the address for a valid Stellar address string sub", () => { - const token = jwt.sign({ sub: "GA5XZ7W7Z7W7Z7W7Z7W7Z7W7Z7W7Z7W7Z7W7Z7W7" }, SECRET, { expiresIn: "1h" }); + const token = jwt.sign({ sub: "GA5XZ7W7Z7W7Z7W7Z7W7Z7W7Z7W7Z7W7Z7W7Z7W7" }, SECRET, { + expiresIn: "1h", + }); expect(extractWalletFromToken(token, SECRET)).toBe("GA5XZ7W7Z7W7Z7W7Z7W7Z7W7Z7W7Z7W7Z7W7Z7W7"); }); diff --git a/tests/unit/horizon-response.test.ts b/tests/unit/horizon-response.test.ts index e3cf756..6e2ca1a 100644 --- a/tests/unit/horizon-response.test.ts +++ b/tests/unit/horizon-response.test.ts @@ -11,7 +11,9 @@ describe("Horizon response normalization", () => { memo: null, memoType: "text", }); - expect(normalizeHorizonPayment({ type: "payment", amount: "5", to: "GABC", asset_code: "USDC" })).toMatchObject({ + expect( + normalizeHorizonPayment({ type: "payment", amount: "5", to: "GABC", asset_code: "USDC" }) + ).toMatchObject({ destination: "GABC", assetCode: "USDC", assetIssuer: null, @@ -20,6 +22,8 @@ describe("Horizon response normalization", () => { it("returns typed validation errors for malformed required fields", () => { expect(() => normalizeHorizonTransaction({})).toThrow(HorizonValidationError); - expect(() => normalizeHorizonPayment({ type: "payment", amount: 5 })).toThrow(HorizonValidationError); + expect(() => normalizeHorizonPayment({ type: "payment", amount: 5 })).toThrow( + HorizonValidationError + ); }); }); diff --git a/tests/unit/invoice-batch-publish.test.ts b/tests/unit/invoice-batch-publish.test.ts index 350ebcc..cf44cae 100644 --- a/tests/unit/invoice-batch-publish.test.ts +++ b/tests/unit/invoice-batch-publish.test.ts @@ -116,7 +116,7 @@ describe("InvoiceService.publishInvoicesBatch", () => { stubInvoices([draftInvoice("a")]); await expect( - service.publishInvoicesBatch({ invoiceIds: ["a"], sellerId: SELLER_ID }), + service.publishInvoicesBatch({ invoiceIds: ["a"], sellerId: SELLER_ID }) ).resolves.toMatchObject({ count: 1 }); }); }); @@ -134,7 +134,7 @@ describe("InvoiceService.publishInvoicesBatch", () => { ]); await expect( - service.publishInvoicesBatch({ invoiceIds: ["a", "b", "c"], sellerId: SELLER_ID }), + service.publishInvoicesBatch({ invoiceIds: ["a", "b", "c"], sellerId: SELLER_ID }) ).rejects.toBeInstanceOf(ServiceError); expect(dataSource.transaction).not.toHaveBeenCalled(); @@ -146,7 +146,7 @@ describe("InvoiceService.publishInvoicesBatch", () => { stubInvoices([good, draftInvoice("b", { ipfsHash: null })]); await expect( - service.publishInvoicesBatch({ invoiceIds: ["a", "b"], sellerId: SELLER_ID }), + service.publishInvoicesBatch({ invoiceIds: ["a", "b"], sellerId: SELLER_ID }) ).rejects.toBeInstanceOf(ServiceError); expect(good.status).toBe(InvoiceStatus.DRAFT); @@ -161,7 +161,7 @@ describe("InvoiceService.publishInvoicesBatch", () => { }); await expect( - service.publishInvoicesBatch({ invoiceIds: ["a", "b"], sellerId: SELLER_ID }), + service.publishInvoicesBatch({ invoiceIds: ["a", "b"], sellerId: SELLER_ID }) ).rejects.toThrow("deadlock detected"); expect(transactionCommitted).toBe(false); @@ -185,8 +185,9 @@ describe("InvoiceService.publishInvoicesBatch", () => { expect(error.code).toBe("batch_publish_rejected"); expect(error.statusCode).toBe(400); - const rejections = (error.details as { rejections: Array<{ invoiceId: string; code: string }> }) - .rejections; + const rejections = ( + error.details as { rejections: Array<{ invoiceId: string; code: string }> } + ).rejections; expect(rejections.map((r) => r.invoiceId).sort()).toEqual(["b", "c", "d"]); expect(rejections.find((r) => r.invoiceId === "b")?.code).toBe("invalid_status_transition"); expect(rejections.find((r) => r.invoiceId === "c")?.code).toBe("invoice_not_publishable"); @@ -200,8 +201,9 @@ describe("InvoiceService.publishInvoicesBatch", () => { .publishInvoicesBatch({ invoiceIds: ["a", "missing"], sellerId: SELLER_ID }) .catch((e) => e)) as ServiceError; - const rejections = (error.details as { rejections: Array<{ invoiceId: string; code: string }> }) - .rejections; + const rejections = ( + error.details as { rejections: Array<{ invoiceId: string; code: string }> } + ).rejections; expect(rejections).toEqual([ { invoiceId: "missing", code: "invoice_not_found", message: "Invoice not found" }, ]); @@ -239,17 +241,19 @@ describe("InvoiceService.publishInvoicesBatch", () => { describe("preconditions", () => { it("rejects an empty batch", async () => { await expect( - service.publishInvoicesBatch({ invoiceIds: [], sellerId: SELLER_ID }), + service.publishInvoicesBatch({ invoiceIds: [], sellerId: SELLER_ID }) ).rejects.toMatchObject({ code: "empty_batch", statusCode: 400 }); }); it("rejects the whole batch when the seller is not KYC approved", async () => { stubInvoices([ - draftInvoice("a", { seller: { ...approvedSeller(), kycStatus: KYCStatus.PENDING } as never }), + draftInvoice("a", { + seller: { ...approvedSeller(), kycStatus: KYCStatus.PENDING } as never, + }), ]); await expect( - service.publishInvoicesBatch({ invoiceIds: ["a"], sellerId: SELLER_ID }), + service.publishInvoicesBatch({ invoiceIds: ["a"], sellerId: SELLER_ID }) ).rejects.toMatchObject({ code: "kyc_approval_required", statusCode: 403 }); expect(dataSource.transaction).not.toHaveBeenCalled(); @@ -263,7 +267,7 @@ describe("InvoiceService.publishInvoicesBatch", () => { stubInvoices([draftInvoice("a")]); await expect( - noDbService.publishInvoicesBatch({ invoiceIds: ["a"], sellerId: SELLER_ID }), + noDbService.publishInvoicesBatch({ invoiceIds: ["a"], sellerId: SELLER_ID }) ).rejects.toMatchObject({ code: "batch_publish_unavailable", statusCode: 503 }); }); }); diff --git a/tests/unit/invoice-state-machine.test.ts b/tests/unit/invoice-state-machine.test.ts index cc5b72c..1cfd181 100644 --- a/tests/unit/invoice-state-machine.test.ts +++ b/tests/unit/invoice-state-machine.test.ts @@ -61,7 +61,9 @@ function createService(invoice: Invoice): InvoiceService { count: jest.fn().mockResolvedValue(0), create: jest.fn().mockImplementation((data: Partial) => data as Invoice), }; - const mockIPFS = { uploadFile: jest.fn() } as unknown as import("../../src/services/ipfs.service").IPFSService; + const mockIPFS = { + uploadFile: jest.fn(), + } as unknown as import("../../src/services/ipfs.service").IPFSService; return new InvoiceService({ invoiceRepository: mockRepo, ipfsService: mockIPFS }); } @@ -90,7 +92,7 @@ describe("Invoice state machine — invalid transitions blocked (issue #110)", ( const service = createService(invoice); await expect( - service.publishInvoice({ invoiceId: invoice.id, sellerId: SELLER_ID }), + service.publishInvoice({ invoiceId: invoice.id, sellerId: SELLER_ID }) ).rejects.toMatchObject({ code: "invalid_status_transition", }); @@ -101,7 +103,7 @@ describe("Invoice state machine — invalid transitions blocked (issue #110)", ( const service = createService(invoice); await expect( - service.publishInvoice({ invoiceId: invoice.id, sellerId: SELLER_ID }), + service.publishInvoice({ invoiceId: invoice.id, sellerId: SELLER_ID }) ).rejects.toMatchObject({ code: "invalid_status_transition", }); @@ -112,7 +114,7 @@ describe("Invoice state machine — invalid transitions blocked (issue #110)", ( const service = createService(invoice); await expect( - service.publishInvoice({ invoiceId: invoice.id, sellerId: SELLER_ID }), + service.publishInvoice({ invoiceId: invoice.id, sellerId: SELLER_ID }) ).rejects.toMatchObject({ code: "invalid_status_transition", }); @@ -142,7 +144,7 @@ describe("Invoice state machine — invalid transitions blocked (issue #110)", ( const service = createService(invoice); return expect( - service.publishInvoice({ invoiceId: invoice.id, sellerId: SELLER_ID }), + service.publishInvoice({ invoiceId: invoice.id, sellerId: SELLER_ID }) ).rejects.toBeInstanceOf(ServiceError); }); @@ -151,7 +153,7 @@ describe("Invoice state machine — invalid transitions blocked (issue #110)", ( const service = createService(invoice); return expect( - service.publishInvoice({ invoiceId: invoice.id, sellerId: SELLER_ID }), + service.publishInvoice({ invoiceId: invoice.id, sellerId: SELLER_ID }) ).rejects.toBeInstanceOf(ServiceError); }); }); diff --git a/tests/unit/ip-whitelist.middleware.test.ts b/tests/unit/ip-whitelist.middleware.test.ts index 5e93af4..7578531 100644 --- a/tests/unit/ip-whitelist.middleware.test.ts +++ b/tests/unit/ip-whitelist.middleware.test.ts @@ -163,4 +163,4 @@ describe("ipWhitelistMiddleware", () => { expect(next).not.toHaveBeenCalled(); expect(res.status).toHaveBeenCalledWith(403); }); -}); \ No newline at end of file +}); diff --git a/tests/unit/kyc-admin-routes.test.ts b/tests/unit/kyc-admin-routes.test.ts index 00ddb4a..7a27bab 100644 --- a/tests/unit/kyc-admin-routes.test.ts +++ b/tests/unit/kyc-admin-routes.test.ts @@ -107,7 +107,9 @@ describe("KYC admin routes — structured logging", () => { }); it("falls back to the reviewer id when the reviewer has no user record", async () => { - stubUsers([{ id: "user-1", stellarAddress: "GABCDEFGHIJKLMNOP", kycStatus: KYCStatus.PENDING }]); + stubUsers([ + { id: "user-1", stellarAddress: "GABCDEFGHIJKLMNOP", kycStatus: KYCStatus.PENDING }, + ]); req.body = { userId: "user-1", reviewerId: "external-reviewer" }; await approveKYC(req, res, mockDataSource); diff --git a/tests/unit/marketplace-cursor-pagination.test.ts b/tests/unit/marketplace-cursor-pagination.test.ts index 3510461..50a76e7 100644 --- a/tests/unit/marketplace-cursor-pagination.test.ts +++ b/tests/unit/marketplace-cursor-pagination.test.ts @@ -70,7 +70,7 @@ describe("MarketplaceService.getPublishedInvoicesByCursor", () => { expect(repo.findPublishedInvoicesByCursor).toHaveBeenCalledWith( expect.objectContaining({ status: [InvoiceStatus.PUBLISHED] }), - expect.objectContaining({ sortField: "amount", order: "DESC", limit: 10, cursor: null }), + expect.objectContaining({ sortField: "amount", order: "DESC", limit: 10, cursor: null }) ); expect(result.data).toEqual([ @@ -101,7 +101,7 @@ describe("MarketplaceService.getPublishedInvoicesByCursor", () => { expect(repo.findPublishedInvoicesByCursor).toHaveBeenCalledWith( expect.anything(), - expect.objectContaining({ limit: 100 }), + expect.objectContaining({ limit: 100 }) ); }); @@ -116,7 +116,7 @@ describe("MarketplaceService.getPublishedInvoicesByCursor", () => { expect(repo.findPublishedInvoicesByCursor).toHaveBeenCalledWith( expect.anything(), - expect.objectContaining({ limit: 1 }), + expect.objectContaining({ limit: 1 }) ); }); @@ -142,7 +142,7 @@ describe("MarketplaceService.getPublishedInvoicesByCursor", () => { order: "ASC", limit: 20, cursor: "prior-cursor", - }), + }) ); }); @@ -154,7 +154,7 @@ describe("MarketplaceService.getPublishedInvoicesByCursor", () => { const legacyService = new MarketplaceService({ marketplaceRepository: legacyRepo }); await expect( - legacyService.getPublishedInvoicesByCursor({}, { sortField: "amount", limit: 10 }), + legacyService.getPublishedInvoicesByCursor({}, { sortField: "amount", limit: 10 }) ).rejects.toThrow(/does not implement findPublishedInvoicesByCursor/); }); }); @@ -192,7 +192,7 @@ describe("TypeORMMarketplaceRepository.findPublishedInvoicesByCursor (via create mockedPaginateQuery.mockClear(); await service.getPublishedInvoicesByCursor({}, { sortField, limit: 10 }); expect(mockedPaginateQuery).toHaveBeenCalledWith( - expect.objectContaining({ cursorField: expectedCursorField }), + expect.objectContaining({ cursorField: expectedCursorField }) ); } }); diff --git a/tests/unit/pagination.test.ts b/tests/unit/pagination.test.ts index b17afd1..b3fa497 100644 --- a/tests/unit/pagination.test.ts +++ b/tests/unit/pagination.test.ts @@ -65,7 +65,7 @@ describe("queryInvoicesPage", () => { expect(mockQueryBuilder.andWhere).toHaveBeenCalledWith( "(invoice.createdAt < :createdAt OR (invoice.createdAt = :createdAt AND invoice.id < :id))", - { createdAt: new Date("2024-01-01T00:00:00.000Z"), id: "invoice-5" }, + { createdAt: new Date("2024-01-01T00:00:00.000Z"), id: "invoice-5" } ); }); @@ -118,7 +118,7 @@ describe("queryInvoicesPage", () => { { sellerId: "seller-1", status: InvoiceStatus.FUNDED }, null, 10, - mockDataSource, + mockDataSource ); expect(mockQueryBuilder.andWhere).toHaveBeenCalledWith("invoice.sellerId = :sellerId", { @@ -136,7 +136,7 @@ describe("queryInvoicesPage", () => { { status: [InvoiceStatus.DRAFT, InvoiceStatus.PUBLISHED] }, null, 10, - mockDataSource, + mockDataSource ); expect(mockQueryBuilder.andWhere).toHaveBeenCalledWith("invoice.status IN (:...statuses)", { @@ -159,14 +159,20 @@ describe("queryInvoicesPage", () => { makeInvoice({ id: `invoice-${i + 1}`, createdAt: new Date(`2024-01-${String(10 - i).padStart(2, "0")}T00:00:00.000Z`), - }), + }) ); // Page 1: limit 5, returns invoices 1-5 (newest) mockQueryBuilder.getMany.mockResolvedValueOnce(allInvoices.slice(0, 6)); // 6 because take = limit+1 const page1 = await queryInvoicesPage({}, null, 5, mockDataSource); - expect(page1.data.map((i) => i.id)).toEqual(["invoice-1", "invoice-2", "invoice-3", "invoice-4", "invoice-5"]); + expect(page1.data.map((i) => i.id)).toEqual([ + "invoice-1", + "invoice-2", + "invoice-3", + "invoice-4", + "invoice-5", + ]); expect(page1.has_more).toBe(true); expect(page1.next_cursor).not.toBeNull(); @@ -184,7 +190,13 @@ describe("queryInvoicesPage", () => { const page2 = await queryInvoicesPage({}, page1.next_cursor, 5, mockDataSource); expect(page2.data).toHaveLength(5); - expect(page2.data.map((i) => i.id)).toEqual(["invoice-6", "invoice-7", "invoice-8", "invoice-9", "invoice-10"]); + expect(page2.data.map((i) => i.id)).toEqual([ + "invoice-6", + "invoice-7", + "invoice-8", + "invoice-9", + "invoice-10", + ]); expect(page2.has_more).toBe(false); // Newly inserted invoice does not appear in page 2 @@ -193,8 +205,16 @@ describe("queryInvoicesPage", () => { // No original invoice skipped between page 1 and page 2 const allPageIds = [...page1.data, ...page2.data].map((i) => i.id); expect(allPageIds).toEqual([ - "invoice-1", "invoice-2", "invoice-3", "invoice-4", "invoice-5", - "invoice-6", "invoice-7", "invoice-8", "invoice-9", "invoice-10", + "invoice-1", + "invoice-2", + "invoice-3", + "invoice-4", + "invoice-5", + "invoice-6", + "invoice-7", + "invoice-8", + "invoice-9", + "invoice-10", ]); // Combined pages cover all 10 original invoices exactly once (no duplicates) diff --git a/tests/unit/query-pagination.utils.test.ts b/tests/unit/query-pagination.utils.test.ts index 813d0a3..f152aeb 100644 --- a/tests/unit/query-pagination.utils.test.ts +++ b/tests/unit/query-pagination.utils.test.ts @@ -68,7 +68,9 @@ describe("paginateQuery", () => { it("uses a returned cursor to fetch the subsequent page, filtering strictly past it", async () => { const cursor = encodeQueryCursor("row.createdAt", new Date("2024-01-02T00:00:00.000Z")); - const qb = makeQueryBuilder([makeRow({ id: "3", createdAt: new Date("2024-01-01T00:00:00.000Z") })]); + const qb = makeQueryBuilder([ + makeRow({ id: "3", createdAt: new Date("2024-01-01T00:00:00.000Z") }), + ]); const result = await paginateQuery({ queryBuilder: qb, @@ -155,7 +157,7 @@ describe("paginateQuery", () => { cursorField: "row.createdAt", limit: 5, cursor, - }), + }) ).rejects.toThrow(/was encoded for field "row.score"/); }); @@ -168,7 +170,7 @@ describe("paginateQuery", () => { cursorField: "row.createdAt", limit: 5, cursor: "not-valid-base64-json!!", - }), + }) ).rejects.toThrow(/Invalid cursor/); }); @@ -176,11 +178,11 @@ describe("paginateQuery", () => { const qb = makeQueryBuilder([]); await expect( - paginateQuery({ queryBuilder: qb, cursorField: "row.createdAt", limit: 0 }), + paginateQuery({ queryBuilder: qb, cursorField: "row.createdAt", limit: 0 }) ).rejects.toThrow(/positive integer/); await expect( - paginateQuery({ queryBuilder: qb, cursorField: "row.createdAt", limit: 1.5 }), + paginateQuery({ queryBuilder: qb, cursorField: "row.createdAt", limit: 1.5 }) ).rejects.toThrow(/positive integer/); }); @@ -188,7 +190,7 @@ describe("paginateQuery", () => { const qb = makeQueryBuilder([]); await expect( - paginateQuery({ queryBuilder: qb, cursorField: "createdAt", limit: 5 }), + paginateQuery({ queryBuilder: qb, cursorField: "createdAt", limit: 5 }) ).rejects.toThrow(/Invalid cursorField/); }); @@ -258,7 +260,7 @@ describe("paginateQuery", () => { expect(qb.andWhere).toHaveBeenCalledWith( "(row.score < :cursor_row_score OR (row.score = :cursor_row_score AND row.id > :cursor_row_id))", - { cursor_row_score: 90, cursor_row_id: "2" }, + { cursor_row_score: 90, cursor_row_id: "2" } ); }); @@ -276,7 +278,7 @@ describe("paginateQuery", () => { expect(qb.andWhere).toHaveBeenCalledWith( "(row.score > :cursor_row_score OR (row.score = :cursor_row_score AND row.id > :cursor_row_id))", - { cursor_row_score: 90, cursor_row_id: "2" }, + { cursor_row_score: 90, cursor_row_id: "2" } ); }); }); @@ -295,7 +297,10 @@ describe("encodeQueryCursor / decodeQueryCursor", () => { it("round-trips a Date value as an ISO string", () => { const date = new Date("2024-06-15T12:00:00.000Z"); const cursor = encodeQueryCursor("row.createdAt", date); - expect(decodeQueryCursor(cursor)).toEqual({ field: "row.createdAt", value: date.toISOString() }); + expect(decodeQueryCursor(cursor)).toEqual({ + field: "row.createdAt", + value: date.toISOString(), + }); }); it("produces an opaque base64 string that does not leak plaintext field/value", () => { diff --git a/tests/unit/reconciliation-retry.test.ts b/tests/unit/reconciliation-retry.test.ts index eca6989..f883aa8 100644 --- a/tests/unit/reconciliation-retry.test.ts +++ b/tests/unit/reconciliation-retry.test.ts @@ -16,7 +16,7 @@ describe("classifyReconciliationError", () => { describe("transient provider failures are retryable", () => { it("classifies an explicit Horizon 5xx/429 provider error as retryable", () => { const decision = classifyReconciliationError( - new RetryableHorizonError("Transient Horizon response: 503"), + new RetryableHorizonError("Transient Horizon response: 503") ); expect(decision.retryable).toBe(true); @@ -28,8 +28,8 @@ describe("classifyReconciliationError", () => { new ServiceError( "horizon_unavailable", "Horizon is temporarily unavailable. Please retry later.", - 503, - ), + 503 + ) ); expect(decision).toMatchObject({ @@ -77,7 +77,7 @@ describe("classifyReconciliationError", () => { describe("permanent validation failures are NOT retryable", () => { it("classifies a malformed response error as permanent", () => { const decision = classifyReconciliationError( - new ServiceError("invalid_amount", "Invalid decimal amount: abc", 500), + new ServiceError("invalid_amount", "Invalid decimal amount: abc", 500) ); expect(decision.retryable).toBe(false); @@ -89,8 +89,8 @@ describe("classifyReconciliationError", () => { new ServiceError( "horizon_request_failed", "Horizon rejected the verification request.", - 502, - ), + 502 + ) ); expect(decision.retryable).toBe(false); @@ -99,11 +99,7 @@ describe("classifyReconciliationError", () => { it("classifies a business-rule invalid_payment error as permanent", () => { const decision = classifyReconciliationError( - new ServiceError( - "invalid_payment", - "No Stellar payment operation matched.", - 422, - ), + new ServiceError("invalid_payment", "No Stellar payment operation matched.", 422) ); expect(decision.retryable).toBe(false); @@ -112,7 +108,7 @@ describe("classifyReconciliationError", () => { it("classifies a not-found error as permanent", () => { const decision = classifyReconciliationError( - new ServiceError("transaction_not_found", "Transaction not found.", 404), + new ServiceError("transaction_not_found", "Transaction not found.", 404) ); expect(decision.retryable).toBe(false); @@ -121,11 +117,7 @@ describe("classifyReconciliationError", () => { it("classifies a reconciliation conflict as permanent", () => { const decision = classifyReconciliationError( - new ServiceError( - "reconciliation_conflict", - "Investment is already confirmed.", - 409, - ), + new ServiceError("reconciliation_conflict", "Investment is already confirmed.", 409) ); expect(decision.retryable).toBe(false); @@ -143,7 +135,7 @@ describe("classifyReconciliationError", () => { it("exposes the attempt number it was classified at", () => { const decision = classifyReconciliationError( new ServiceError("horizon_unavailable", "down", 503), - 3, + 3 ); expect(decision.attempt).toBe(3); @@ -175,11 +167,10 @@ describe("classifyReconciliationError", () => { const nonErrors: unknown[] = [undefined, null, "text", 42, { status: 200 }]; for (const value of nonErrors) { - const decision: ReconciliationRetryDecision = - classifyReconciliationError(value); + const decision: ReconciliationRetryDecision = classifyReconciliationError(value); expect(typeof decision.retryable).toBe("boolean"); expect(["transient_provider", "permanent_validation"]).toContain( - decision.kind as ReconciliationFailureKind, + decision.kind as ReconciliationFailureKind ); } }); diff --git a/tests/unit/response-envelope.test.ts b/tests/unit/response-envelope.test.ts index 8fda0d6..c0900e2 100644 --- a/tests/unit/response-envelope.test.ts +++ b/tests/unit/response-envelope.test.ts @@ -1,60 +1,60 @@ import { buildPaginatedResponse } from "../../src/utils/response-envelope.utils"; describe("buildPaginatedResponse", () => { - it("returns the correct envelope structure with items and meta", () => { - const items = [{ id: "1" }, { id: "2" }]; - const result = buildPaginatedResponse(items, 10, 2, "cursor-abc"); - - expect(result).toEqual({ - success: true, - data: items, - meta: { - total: 10, - limit: 2, - hasNextPage: true, - nextCursor: "cursor-abc", - }, - }); + it("returns the correct envelope structure with items and meta", () => { + const items = [{ id: "1" }, { id: "2" }]; + const result = buildPaginatedResponse(items, 10, 2, "cursor-abc"); + + expect(result).toEqual({ + success: true, + data: items, + meta: { + total: 10, + limit: 2, + hasNextPage: true, + nextCursor: "cursor-abc", + }, }); + }); - it("sets hasNextPage to false and nextCursor to null when no cursor is provided", () => { - const items = [{ id: "1" }]; - const result = buildPaginatedResponse(items, 1, 20); + it("sets hasNextPage to false and nextCursor to null when no cursor is provided", () => { + const items = [{ id: "1" }]; + const result = buildPaginatedResponse(items, 1, 20); - expect(result.meta.hasNextPage).toBe(false); - expect(result.meta.nextCursor).toBeNull(); - }); + expect(result.meta.hasNextPage).toBe(false); + expect(result.meta.nextCursor).toBeNull(); + }); - it("sets hasNextPage to false when nextCursor is an empty string", () => { - const items: number[] = []; - const result = buildPaginatedResponse(items, 0, 20, ""); + it("sets hasNextPage to false when nextCursor is an empty string", () => { + const items: number[] = []; + const result = buildPaginatedResponse(items, 0, 20, ""); - expect(result.meta.hasNextPage).toBe(false); - expect(result.meta.nextCursor).toBeNull(); - }); + expect(result.meta.hasNextPage).toBe(false); + expect(result.meta.nextCursor).toBeNull(); + }); - it("handles an empty items array", () => { - const result = buildPaginatedResponse([], 0, 20); + it("handles an empty items array", () => { + const result = buildPaginatedResponse([], 0, 20); - expect(result.data).toEqual([]); - expect(result.meta.total).toBe(0); - expect(result.meta.hasNextPage).toBe(false); - }); + expect(result.data).toEqual([]); + expect(result.meta.total).toBe(0); + expect(result.meta.hasNextPage).toBe(false); + }); - it("preserves the generic type of the items array", () => { - interface Invoice { - id: string; - amount: string; - } + it("preserves the generic type of the items array", () => { + interface Invoice { + id: string; + amount: string; + } - const invoices: Invoice[] = [ - { id: "inv-1", amount: "5000" }, - { id: "inv-2", amount: "10000" }, - ]; + const invoices: Invoice[] = [ + { id: "inv-1", amount: "5000" }, + { id: "inv-2", amount: "10000" }, + ]; - const result = buildPaginatedResponse(invoices, 2, 10); + const result = buildPaginatedResponse(invoices, 2, 10); - expect(result.data[0].amount).toBe("5000"); - expect(result.data[1].id).toBe("inv-2"); - }); -}); \ No newline at end of file + expect(result.data[0].amount).toBe("5000"); + expect(result.data[1].id).toBe("inv-2"); + }); +}); diff --git a/tests/unit/services/investment-yield.test.ts b/tests/unit/services/investment-yield.test.ts index a3dc4a6..d907e0b 100644 --- a/tests/unit/services/investment-yield.test.ts +++ b/tests/unit/services/investment-yield.test.ts @@ -3,14 +3,14 @@ import { computeInvestorReturn } from "../../../src/lib/investor-return"; function computeProRataDistribution( investorAmounts: bigint[], totalSettlementStroops: bigint, - platformFeeBps: number, + platformFeeBps: number ): { payouts: bigint[]; fee: bigint } { const totalFunded = investorAmounts.reduce((a, b) => a + b, 0n); const fee = (totalSettlementStroops * BigInt(platformFeeBps)) / 10_000n; const distributable = totalSettlementStroops - fee; const payouts = investorAmounts.map((amount) => - computeInvestorReturn(amount, totalFunded, distributable), + computeInvestorReturn(amount, totalFunded, distributable) ); return { payouts, fee }; @@ -23,11 +23,7 @@ describe("Investment pro-rata yield distribution", () => { const investorB = 4_000_000_000_000n; const settlement = 11_000_000_000_000n; - const { payouts, fee } = computeProRataDistribution( - [investorA, investorB], - settlement, - 0, - ); + const { payouts, fee } = computeProRataDistribution([investorA, investorB], settlement, 0); expect(fee).toBe(0n); expect(payouts[0] + payouts[1]).toBe(settlement); @@ -40,11 +36,7 @@ describe("Investment pro-rata yield distribution", () => { const investorB = 4_000_000_000_000n; const settlement = 11_000_000_000_000n; - const { payouts, fee } = computeProRataDistribution( - [investorA, investorB], - settlement, - 250, - ); + const { payouts, fee } = computeProRataDistribution([investorA, investorB], settlement, 250); const expectedFee = (11_000_000_000_000n * 250n) / 10_000n; expect(fee).toBe(expectedFee); @@ -57,7 +49,7 @@ describe("Investment pro-rata yield distribution", () => { const { payouts } = computeProRataDistribution( [5_000_000_000_000n, 5_000_000_000_000n], settlement, - 0, + 0 ); expect(payouts[0]).toBe(payouts[1]); @@ -73,7 +65,7 @@ describe("Investment pro-rata yield distribution", () => { const { payouts, fee } = computeProRataDistribution( [amount, amount, amount], settlement, - 100, + 100 ); const expectedFee = (settlement * 100n) / 10_000n; @@ -92,7 +84,7 @@ describe("Investment pro-rata yield distribution", () => { const { payouts, fee } = computeProRataDistribution( [investorA, investorB, investorC], settlement, - 250, + 250 ); const expectedFee = (settlement * 250n) / 10_000n; @@ -161,11 +153,7 @@ describe("Investment pro-rata yield distribution", () => { const amount = 1_000_000_000_000n; const settlement = 10_000_000_000_003n; - const { payouts } = computeProRataDistribution( - [amount, amount, amount], - settlement, - 0, - ); + const { payouts } = computeProRataDistribution([amount, amount, amount], settlement, 0); const totalPayout = payouts.reduce((a, b) => a + b, 0n); expect(totalPayout).toBeLessThanOrEqual(settlement); @@ -209,7 +197,11 @@ describe("Investment pro-rata yield distribution", () => { it("0% fee returns zero fee and full settlement as distributable", () => { const settlement = 10_000_000_000_000n; - const { fee } = computeProRataDistribution([5_000_000_000_000n, 5_000_000_000_000n], settlement, 0); + const { fee } = computeProRataDistribution( + [5_000_000_000_000n, 5_000_000_000_000n], + settlement, + 0 + ); expect(fee).toBe(0n); }); @@ -217,7 +209,11 @@ describe("Investment pro-rata yield distribution", () => { it("2.5% fee (250 bps) is calculated correctly", () => { const settlement = 100_000_000_000_000n; - const { fee } = computeProRataDistribution([50_000_000_000_000n, 50_000_000_000_000n], settlement, 250); + const { fee } = computeProRataDistribution( + [50_000_000_000_000n, 50_000_000_000_000n], + settlement, + 250 + ); expect(fee).toBe(2_500_000_000_000n); }); @@ -254,7 +250,7 @@ describe("Investment pro-rata yield distribution", () => { const result = computeInvestorReturn( 1_000_000_000_000n, 1_000_000_000_001n, - 1_000_000_000_000n, + 1_000_000_000_000n ); expect(typeof result).toBe("bigint"); expect(Number.isFinite(Number(result))).toBe(true); diff --git a/tests/unit/services/stellar/event-indexer.service.test.ts b/tests/unit/services/stellar/event-indexer.service.test.ts index 7405b0b..e6da425 100644 --- a/tests/unit/services/stellar/event-indexer.service.test.ts +++ b/tests/unit/services/stellar/event-indexer.service.test.ts @@ -49,7 +49,7 @@ describe("EventIndexerService (Issue #135)", () => { describe("Initialization", () => { it("should throw an error when contractIds array is empty", () => { expect(() => new EventIndexerService({ contractIds: [] })).toThrow( - "At least one contractId is required.", + "At least one contractId is required." ); }); @@ -130,7 +130,7 @@ describe("EventIndexerService (Issue #135)", () => { startLedger: 1999, limit: 50, filters: [{ type: "contract", contractIds: [ESCROW_CONTRACT_ID] }], - }), + }) ); }); }); @@ -161,7 +161,7 @@ describe("EventIndexerService (Issue #135)", () => { expect(mockEventLogRepo.save).toHaveBeenCalled(); expect(mockInvoiceRepo.findOne).toHaveBeenCalledWith({ where: { id: "INV-100" } }); expect(mockInvoiceRepo.save).toHaveBeenCalledWith( - expect.objectContaining({ id: "INV-100", status: InvoiceStatus.PUBLISHED }), + expect.objectContaining({ id: "INV-100", status: InvoiceStatus.PUBLISHED }) ); }); @@ -189,7 +189,7 @@ describe("EventIndexerService (Issue #135)", () => { await service.ingestEvents([decodedEvent]); expect(mockInvoiceRepo.save).toHaveBeenCalledWith( - expect.objectContaining({ id: "INV-100", status: InvoiceStatus.FUNDED }), + expect.objectContaining({ id: "INV-100", status: InvoiceStatus.FUNDED }) ); }); @@ -217,7 +217,7 @@ describe("EventIndexerService (Issue #135)", () => { await service.ingestEvents([decodedEvent]); expect(mockInvoiceRepo.save).toHaveBeenCalledWith( - expect.objectContaining({ id: "INV-100", status: InvoiceStatus.SETTLED }), + expect.objectContaining({ id: "INV-100", status: InvoiceStatus.SETTLED }) ); }); @@ -245,7 +245,7 @@ describe("EventIndexerService (Issue #135)", () => { await service.ingestEvents([decodedEvent]); expect(mockInvoiceRepo.save).toHaveBeenCalledWith( - expect.objectContaining({ id: "INV-100", status: InvoiceStatus.SETTLED }), + expect.objectContaining({ id: "INV-100", status: InvoiceStatus.SETTLED }) ); }); }); @@ -275,7 +275,7 @@ describe("EventIndexerService (Issue #135)", () => { service.stop(); expect(mockLogger.info).toHaveBeenCalledWith( "Starting Soroban event indexer service", - expect.any(Object), + expect.any(Object) ); expect(mockLogger.info).toHaveBeenCalledWith("Stopped Soroban event indexer service"); }); diff --git a/tests/unit/services/stellar/invoice-escrow-contract.service.test.ts b/tests/unit/services/stellar/invoice-escrow-contract.service.test.ts index 019720d..3520381 100644 --- a/tests/unit/services/stellar/invoice-escrow-contract.service.test.ts +++ b/tests/unit/services/stellar/invoice-escrow-contract.service.test.ts @@ -34,20 +34,15 @@ describe("InvoiceEscrowContractService", () => { }); it("should initialize correctly with string contract ID", () => { - const stringInitService = new InvoiceEscrowContractService( - ESCROW_CONTRACT_ID, - mockLogger, - ); + const stringInitService = new InvoiceEscrowContractService(ESCROW_CONTRACT_ID, mockLogger); expect(stringInitService.contractId).toBe(ESCROW_CONTRACT_ID); }); it("should throw error if contractId is empty", () => { - expect(() => new InvoiceEscrowContractService("")).toThrow( - "contractId is required.", + expect(() => new InvoiceEscrowContractService("")).toThrow("contractId is required."); + expect(() => new InvoiceEscrowContractService({ contractId: "" })).toThrow( + "contractId is required." ); - expect( - () => new InvoiceEscrowContractService({ contractId: "" }), - ).toThrow("contractId is required."); }); }); @@ -58,15 +53,11 @@ describe("InvoiceEscrowContractService", () => { TEST_SELLER, TEST_AMOUNT_STROOPS, TEST_DUE_DATE, - TEST_TOKEN, + TEST_TOKEN ); expect(op.body().switch().name).toBe("invokeHostFunction"); - const invokeContractArgs = op - .body() - .invokeHostFunctionOp() - .hostFunction() - .invokeContract(); + const invokeContractArgs = op.body().invokeHostFunctionOp().hostFunction().invokeContract(); expect(invokeContractArgs.functionName().toString()).toBe("create_escrow"); @@ -114,7 +105,7 @@ describe("InvoiceEscrowContractService", () => { sorobanContractId: ESCROW_CONTRACT_ID, sellerAddress: TEST_SELLER, amountStroops: TEST_AMOUNT_STROOPS.toString(), - }, + } ); }); @@ -149,11 +140,7 @@ describe("InvoiceEscrowContractService", () => { it("should construct valid fund_escrow host function invocation", () => { const op = service.buildFundEscrowTx(TEST_INVOICE_ID, TEST_SELLER, TEST_AMOUNT_STROOPS); expect(op.body().switch().name).toBe("invokeHostFunction"); - const invokeContractArgs = op - .body() - .invokeHostFunctionOp() - .hostFunction() - .invokeContract(); + const invokeContractArgs = op.body().invokeHostFunctionOp().hostFunction().invokeContract(); expect(invokeContractArgs.functionName().toString()).toBe("fund_escrow"); const args = invokeContractArgs.args(); @@ -167,11 +154,7 @@ describe("InvoiceEscrowContractService", () => { describe("buildRecordPaymentTx", () => { it("should construct valid record_payment host function invocation", () => { const op = service.buildRecordPaymentTx(TEST_INVOICE_ID, TEST_SELLER, TEST_AMOUNT_STROOPS); - const invokeContractArgs = op - .body() - .invokeHostFunctionOp() - .hostFunction() - .invokeContract(); + const invokeContractArgs = op.body().invokeHostFunctionOp().hostFunction().invokeContract(); expect(invokeContractArgs.functionName().toString()).toBe("record_payment"); const args = invokeContractArgs.args(); @@ -183,11 +166,7 @@ describe("InvoiceEscrowContractService", () => { describe("buildSettleEscrowTx", () => { it("should construct valid settle_escrow host function invocation", () => { const op = service.buildSettleEscrowTx(TEST_INVOICE_ID); - const invokeContractArgs = op - .body() - .invokeHostFunctionOp() - .hostFunction() - .invokeContract(); + const invokeContractArgs = op.body().invokeHostFunctionOp().hostFunction().invokeContract(); expect(invokeContractArgs.functionName().toString()).toBe("settle_escrow"); const args = invokeContractArgs.args(); diff --git a/tests/unit/services/stellar/invoice-token-tx.test.ts b/tests/unit/services/stellar/invoice-token-tx.test.ts index a8a9309..4ca36c3 100644 --- a/tests/unit/services/stellar/invoice-token-tx.test.ts +++ b/tests/unit/services/stellar/invoice-token-tx.test.ts @@ -16,9 +16,7 @@ describe("InvoiceTokenContractService - buildMintTx", () => { }); it("should throw an error when contractId is empty", () => { - expect(() => new InvoiceTokenContractService("")).toThrow( - "contractId is required.", - ); + expect(() => new InvoiceTokenContractService("")).toThrow("contractId is required."); }); it("should construct a valid InvokeHostFunction operation", () => { @@ -37,9 +35,7 @@ describe("InvoiceTokenContractService - buildMintTx", () => { const invokeHostFunctionOp = op.body().invokeHostFunctionOp(); const hostFunction = invokeHostFunctionOp.hostFunction(); - expect(hostFunction.switch().name).toBe( - "hostFunctionTypeInvokeContract", - ); + expect(hostFunction.switch().name).toBe("hostFunctionTypeInvokeContract"); const invokeContractArgs = hostFunction.invokeContract(); const contractAddressScVal = invokeContractArgs.contractAddress(); @@ -52,11 +48,7 @@ describe("InvoiceTokenContractService - buildMintTx", () => { const tokenAmount = 750_000n; const op = service.buildMintTx(TEST_RECIPIENT, tokenAmount); - const invokeContractArgs = op - .body() - .invokeHostFunctionOp() - .hostFunction() - .invokeContract(); + const invokeContractArgs = op.body().invokeHostFunctionOp().hostFunction().invokeContract(); // Verify function name const functionName = invokeContractArgs.functionName().toString(); @@ -83,12 +75,7 @@ describe("InvoiceTokenContractService - buildMintTx", () => { const amountFromString = service.buildMintTx(TEST_RECIPIENT, "1000000"); const getAmount = (operation: xdr.Operation) => { - const args = operation - .body() - .invokeHostFunctionOp() - .hostFunction() - .invokeContract() - .args(); + const args = operation.body().invokeHostFunctionOp().hostFunction().invokeContract().args(); return BigInt(scValToNative(args[1])); }; @@ -105,12 +92,7 @@ describe("InvoiceTokenContractService - buildMintTx", () => { const opLarge = service.buildMintTx(TEST_RECIPIENT, largeAmount); const getAmount = (operation: xdr.Operation) => { - const args = operation - .body() - .invokeHostFunctionOp() - .hostFunction() - .invokeContract() - .args(); + const args = operation.body().invokeHostFunctionOp().hostFunction().invokeContract().args(); return BigInt(scValToNative(args[1])); }; @@ -124,11 +106,7 @@ describe("InvoiceTokenContractService - buildMintTx", () => { describe("mintInvoiceTokens", () => { it("should build and return structured mint result", async () => { - const result = await service.mintInvoiceTokens( - "INV-123", - TEST_RECIPIENT, - 500_000n, - ); + const result = await service.mintInvoiceTokens("INV-123", TEST_RECIPIENT, 500_000n); expect(result.invoiceId).toBe("INV-123"); expect(result.contractId).toBe(TOKEN_CONTRACT_ID); @@ -141,11 +119,7 @@ describe("InvoiceTokenContractService - buildMintTx", () => { describe("buildBalanceTx & getTokenBalance", () => { it("should construct valid balance host function invocation", () => { const op = service.buildBalanceTx(TEST_RECIPIENT); - const invokeContractArgs = op - .body() - .invokeHostFunctionOp() - .hostFunction() - .invokeContract(); + const invokeContractArgs = op.body().invokeHostFunctionOp().hostFunction().invokeContract(); expect(invokeContractArgs.functionName().toString()).toBe("balance"); const args = invokeContractArgs.args(); diff --git a/tests/unit/services/stellar/payment-distributor-settlement.test.ts b/tests/unit/services/stellar/payment-distributor-settlement.test.ts index e732e04..7c8bb80 100644 --- a/tests/unit/services/stellar/payment-distributor-settlement.test.ts +++ b/tests/unit/services/stellar/payment-distributor-settlement.test.ts @@ -18,29 +18,60 @@ describe("PaymentDistributorContractService settlement execution", () => { it("submits and waits for successful ledger confirmation", async () => { const service = new PaymentDistributorContractService({ - contractId, server: createRpc(), networkPassphrase: "Test SDF Network ; September 2015", - platformSecretKey: signer.secret(), verifyDistributorWiring: async () => true, - confirmationPollMs: 0, confirmationAttempts: 2, + contractId, + server: createRpc(), + networkPassphrase: "Test SDF Network ; September 2015", + platformSecretKey: signer.secret(), + verifyDistributorWiring: async () => true, + confirmationPollMs: 0, + confirmationAttempts: 2, }); - await expect(service.distributePayouts({ - invoiceId: "INV-1", totalAmountStroops: 1_000n, feeRecipient, feeBps: 250, - recipients: [{ address: recipient, amountStroops: 975n }], - })).resolves.toEqual({ transactionHash: "tx-hash", ledger: 77 }); + await expect( + service.distributePayouts({ + invoiceId: "INV-1", + totalAmountStroops: 1_000n, + feeRecipient, + feeBps: 250, + recipients: [{ address: recipient, amountStroops: 975n }], + }) + ).resolves.toEqual({ transactionHash: "tx-hash", ledger: 77 }); }); it("stops without settlement when wiring is not initialized", async () => { const service = new PaymentDistributorContractService({ - contractId, server: createRpc(), networkPassphrase: "Test SDF Network ; September 2015", - platformSecretKey: signer.secret(), verifyDistributorWiring: async () => false, + contractId, + server: createRpc(), + networkPassphrase: "Test SDF Network ; September 2015", + platformSecretKey: signer.secret(), + verifyDistributorWiring: async () => false, }); - await expect(service.distributePayouts({ invoiceId: "INV-1", totalAmountStroops: 1_000n, feeRecipient, feeBps: 250, recipients: [{ address: recipient, amountStroops: 975n }] })).rejects.toThrow("not initialized"); + await expect( + service.distributePayouts({ + invoiceId: "INV-1", + totalAmountStroops: 1_000n, + feeRecipient, + feeBps: 250, + recipients: [{ address: recipient, amountStroops: 975n }], + }) + ).rejects.toThrow("not initialized"); }); it("surfaces a reverted transaction", async () => { const service = new PaymentDistributorContractService({ - contractId, server: createRpc("FAILED"), networkPassphrase: "Test SDF Network ; September 2015", - platformSecretKey: signer.secret(), confirmationPollMs: 0, + contractId, + server: createRpc("FAILED"), + networkPassphrase: "Test SDF Network ; September 2015", + platformSecretKey: signer.secret(), + confirmationPollMs: 0, }); - await expect(service.distributePayouts({ invoiceId: "INV-1", totalAmountStroops: 1_000n, feeRecipient, feeBps: 250, recipients: [{ address: recipient, amountStroops: 975n }] })).rejects.toThrow("reverted"); + await expect( + service.distributePayouts({ + invoiceId: "INV-1", + totalAmountStroops: 1_000n, + feeRecipient, + feeBps: 250, + recipients: [{ address: recipient, amountStroops: 975n }], + }) + ).rejects.toThrow("reverted"); }); }); diff --git a/tests/unit/services/stellar/payment-distributor-tx.test.ts b/tests/unit/services/stellar/payment-distributor-tx.test.ts index e6d78f1..fce292c 100644 --- a/tests/unit/services/stellar/payment-distributor-tx.test.ts +++ b/tests/unit/services/stellar/payment-distributor-tx.test.ts @@ -7,7 +7,8 @@ import { describe("PaymentDistributorContractService.buildDistributePayoutsTx (Issue #156)", () => { // A known-valid contract StrKey, reused from the existing // invoice-escrow-contract.service.test.ts fixtures. - const PAYMENT_DISTRIBUTOR_CONTRACT_ID = "CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC"; + const PAYMENT_DISTRIBUTOR_CONTRACT_ID = + "CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC"; const SELLER_ADDRESS = Keypair.random().publicKey(); const INVESTOR_A_ADDRESS = Keypair.random().publicKey(); @@ -38,11 +39,13 @@ describe("PaymentDistributorContractService.buildDistributePayoutsTx (Issue #156 INVOICE_ID, singleRecipient, PLATFORM_FEE_ACCOUNT, - 250, + 250 ); const invokeContractArgs = op.body().invokeHostFunctionOp().hostFunction().invokeContract(); - const invokedContractId = Address.fromScAddress(invokeContractArgs.contractAddress()).toString(); + const invokedContractId = Address.fromScAddress( + invokeContractArgs.contractAddress() + ).toString(); expect(invokedContractId).toBe(PAYMENT_DISTRIBUTOR_CONTRACT_ID); expect(invokedContractId).toBe(service.contractId); @@ -53,7 +56,7 @@ describe("PaymentDistributorContractService.buildDistributePayoutsTx (Issue #156 INVOICE_ID, singleRecipient, PLATFORM_FEE_ACCOUNT, - 250, + 250 ); const functionName = op @@ -112,7 +115,7 @@ describe("PaymentDistributorContractService.buildDistributePayoutsTx (Issue #156 INVOICE_ID, singleRecipient, PLATFORM_FEE_ACCOUNT, - 250, + 250 ); const args = op.body().invokeHostFunctionOp().hostFunction().invokeContract().args(); @@ -127,7 +130,7 @@ describe("PaymentDistributorContractService.buildDistributePayoutsTx (Issue #156 INVOICE_ID, singleRecipient, PLATFORM_FEE_ACCOUNT, - feeBps, + feeBps ); const args = op.body().invokeHostFunctionOp().hostFunction().invokeContract().args(); expect(scValToNative(args[4])).toBe(feeBps); @@ -135,19 +138,19 @@ describe("PaymentDistributorContractService.buildDistributePayoutsTx (Issue #156 it("rejects feeBps above 10000 (100%)", () => { expect(() => - service.buildDistributePayoutsTx(INVOICE_ID, singleRecipient, PLATFORM_FEE_ACCOUNT, 10_001), + service.buildDistributePayoutsTx(INVOICE_ID, singleRecipient, PLATFORM_FEE_ACCOUNT, 10_001) ).toThrow("feeBps must be an integer between 0 and 10000."); }); it("rejects a negative feeBps", () => { expect(() => - service.buildDistributePayoutsTx(INVOICE_ID, singleRecipient, PLATFORM_FEE_ACCOUNT, -1), + service.buildDistributePayoutsTx(INVOICE_ID, singleRecipient, PLATFORM_FEE_ACCOUNT, -1) ).toThrow("feeBps must be an integer between 0 and 10000."); }); it("rejects a non-integer feeBps", () => { expect(() => - service.buildDistributePayoutsTx(INVOICE_ID, singleRecipient, PLATFORM_FEE_ACCOUNT, 12.5), + service.buildDistributePayoutsTx(INVOICE_ID, singleRecipient, PLATFORM_FEE_ACCOUNT, 12.5) ).toThrow("feeBps must be an integer between 0 and 10000."); }); }); @@ -155,7 +158,7 @@ describe("PaymentDistributorContractService.buildDistributePayoutsTx (Issue #156 describe("invalid inputs", () => { it("throws when recipients is empty", () => { expect(() => - service.buildDistributePayoutsTx(INVOICE_ID, [], PLATFORM_FEE_ACCOUNT, 250), + service.buildDistributePayoutsTx(INVOICE_ID, [], PLATFORM_FEE_ACCOUNT, 250) ).toThrow("At least one payout recipient is required."); }); @@ -165,13 +168,13 @@ describe("PaymentDistributorContractService.buildDistributePayoutsTx (Issue #156 ]; expect(() => - service.buildDistributePayoutsTx(INVOICE_ID, recipients, PLATFORM_FEE_ACCOUNT, 250), + service.buildDistributePayoutsTx(INVOICE_ID, recipients, PLATFORM_FEE_ACCOUNT, 250) ).toThrow(); }); it("throws when the platform fee account is invalid", () => { expect(() => - service.buildDistributePayoutsTx(INVOICE_ID, singleRecipient, "not-a-valid-address", 250), + service.buildDistributePayoutsTx(INVOICE_ID, singleRecipient, "not-a-valid-address", 250) ).toThrow(); }); }); diff --git a/tests/unit/stellar-address.test.ts b/tests/unit/stellar-address.test.ts index b9a5676..e897dde 100644 --- a/tests/unit/stellar-address.test.ts +++ b/tests/unit/stellar-address.test.ts @@ -10,9 +10,7 @@ describe("isValidStellarPublicKey", () => { it("returns false for malformed G-addresses", () => { expect(isValidStellarPublicKey("GABC")).toBe(false); expect( - isValidStellarPublicKey( - "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - ), + isValidStellarPublicKey("GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") ).toBe(false); }); diff --git a/tests/unit/stellar-challenge.test.ts b/tests/unit/stellar-challenge.test.ts index 744a335..bad2fcd 100644 --- a/tests/unit/stellar-challenge.test.ts +++ b/tests/unit/stellar-challenge.test.ts @@ -12,7 +12,7 @@ describe("buildWalletChallenge", () => { const { transaction, nonce } = buildWalletChallenge( walletKeypair.publicKey(), TESTNET_PASSPHRASE, - serverKeypair, + serverKeypair ); expect(transaction).toBeInstanceOf(Transaction); @@ -22,7 +22,9 @@ describe("buildWalletChallenge", () => { // Transaction must carry at least one ManageData operation named web_auth_domain const ops = transaction.operations; expect(ops.length).toBeGreaterThan(0); - const managedDataOp = ops.find((op) => op.type === "manageData" && op.name === "web_auth_domain"); + const managedDataOp = ops.find( + (op) => op.type === "manageData" && op.name === "web_auth_domain" + ); expect(managedDataOp).toBeDefined(); // Transaction must be signed by the server keypair @@ -33,20 +35,26 @@ describe("buildWalletChallenge", () => { const serverKeypair = Keypair.random(); expect(() => - buildWalletChallenge("NOT_A_VALID_STELLAR_ADDRESS", TESTNET_PASSPHRASE, serverKeypair), + buildWalletChallenge("NOT_A_VALID_STELLAR_ADDRESS", TESTNET_PASSPHRASE, serverKeypair) ).toThrow(HttpError); - expect(() => - buildWalletChallenge("", TESTNET_PASSPHRASE, serverKeypair), - ).toThrow(HttpError); + expect(() => buildWalletChallenge("", TESTNET_PASSPHRASE, serverKeypair)).toThrow(HttpError); }); it("produces a different nonce on each call", () => { const walletKeypair = Keypair.random(); const serverKeypair = Keypair.random(); - const first = buildWalletChallenge(walletKeypair.publicKey(), TESTNET_PASSPHRASE, serverKeypair); - const second = buildWalletChallenge(walletKeypair.publicKey(), TESTNET_PASSPHRASE, serverKeypair); + const first = buildWalletChallenge( + walletKeypair.publicKey(), + TESTNET_PASSPHRASE, + serverKeypair + ); + const second = buildWalletChallenge( + walletKeypair.publicKey(), + TESTNET_PASSPHRASE, + serverKeypair + ); expect(first.nonce).not.toBe(second.nonce); expect(first.transaction.toXDR()).not.toBe(second.transaction.toXDR()); diff --git a/tests/unit/unit-conversion.test.ts b/tests/unit/unit-conversion.test.ts index de94274..b46b2d0 100644 --- a/tests/unit/unit-conversion.test.ts +++ b/tests/unit/unit-conversion.test.ts @@ -2,112 +2,104 @@ import Decimal from "decimal.js"; import { stroopsToXlm, xlmToStroops } from "../../src/utils/unit-conversion.utils"; describe("stroopsToXlm", () => { - it("converts 10,000,000 stroops to 1.0000000 XLM", () => { - expect(stroopsToXlm(10_000_000n)).toBe("1.0000000"); - }); - - it("converts 1 stroop to 0.0000001 XLM", () => { - expect(stroopsToXlm(1n)).toBe("0.0000001"); - }); - - it("converts 0 stroops to 0.0000000 XLM", () => { - expect(stroopsToXlm(0n)).toBe("0.0000000"); - }); - - it("converts 100,000 XLM worth of stroops without floating point error", () => { - // 100,000 XLM = 1,000,000,000,000 stroops - const stroops = 100_000n * 10_000_000n; - expect(stroopsToXlm(stroops)).toBe("100000.0000000"); - }); - - it("handles large values above MAX_SAFE_INTEGER without precision loss", () => { - // Number.MAX_SAFE_INTEGER (9007199254740991) whole XLM, in stroops - const stroops = 9_007_199_254_740_991n * 10_000_000n; - expect(stroopsToXlm(stroops)).toBe("9007199254740991.0000000"); - }); - - it("handles string input for bigint", () => { - expect(stroopsToXlm("10000000")).toBe("1.0000000"); - expect(stroopsToXlm("1")).toBe("0.0000001"); - }); - - it("handles fractional stroop amounts correctly (truncation)", () => { - // Fractional stroop concept: 1 stroop is the minimum unit - // So 0.5 stroop doesn't exist, but we test boundary - expect(stroopsToXlm(0n)).toBe("0.0000000"); - }); + it("converts 10,000,000 stroops to 1.0000000 XLM", () => { + expect(stroopsToXlm(10_000_000n)).toBe("1.0000000"); + }); + + it("converts 1 stroop to 0.0000001 XLM", () => { + expect(stroopsToXlm(1n)).toBe("0.0000001"); + }); + + it("converts 0 stroops to 0.0000000 XLM", () => { + expect(stroopsToXlm(0n)).toBe("0.0000000"); + }); + + it("converts 100,000 XLM worth of stroops without floating point error", () => { + // 100,000 XLM = 1,000,000,000,000 stroops + const stroops = 100_000n * 10_000_000n; + expect(stroopsToXlm(stroops)).toBe("100000.0000000"); + }); + + it("handles large values above MAX_SAFE_INTEGER without precision loss", () => { + // Number.MAX_SAFE_INTEGER (9007199254740991) whole XLM, in stroops + const stroops = 9_007_199_254_740_991n * 10_000_000n; + expect(stroopsToXlm(stroops)).toBe("9007199254740991.0000000"); + }); + + it("handles string input for bigint", () => { + expect(stroopsToXlm("10000000")).toBe("1.0000000"); + expect(stroopsToXlm("1")).toBe("0.0000001"); + }); + + it("handles fractional stroop amounts correctly (truncation)", () => { + // Fractional stroop concept: 1 stroop is the minimum unit + // So 0.5 stroop doesn't exist, but we test boundary + expect(stroopsToXlm(0n)).toBe("0.0000000"); + }); }); describe("xlmToStroops", () => { - it("converts 1 XLM to 10,000,000 stroops", () => { - expect(xlmToStroops("1.0000000")).toBe(10_000_000n); - }); - - it("converts 0.0000001 XLM to 1 stroop", () => { - expect(xlmToStroops("0.0000001")).toBe(1n); - }); - - it("converts 0 XLM to 0 stroops", () => { - expect(xlmToStroops("0")).toBe(0n); - }); - - it("converts 100,000 XLM to stroops correctly", () => { - expect(xlmToStroops("100000")).toBe(1_000_000_000_000n); - }); - - it("converts string input with decimals correctly", () => { - expect(xlmToStroops("1.5")).toBe(15_000_000n); - expect(xlmToStroops("0.5")).toBe(5_000_000n); - }); - - it("converts number input correctly", () => { - expect(xlmToStroops(1)).toBe(10_000_000n); - expect(xlmToStroops(0)).toBe(0n); - }); - - it("rounds down fractional stroops to the nearest stroop", () => { - // 0.00000015 XLM would be 1.5 stroops, should round down to 1 - expect(xlmToStroops("0.00000015")).toBe(1n); - }); + it("converts 1 XLM to 10,000,000 stroops", () => { + expect(xlmToStroops("1.0000000")).toBe(10_000_000n); + }); + + it("converts 0.0000001 XLM to 1 stroop", () => { + expect(xlmToStroops("0.0000001")).toBe(1n); + }); + + it("converts 0 XLM to 0 stroops", () => { + expect(xlmToStroops("0")).toBe(0n); + }); + + it("converts 100,000 XLM to stroops correctly", () => { + expect(xlmToStroops("100000")).toBe(1_000_000_000_000n); + }); + + it("converts string input with decimals correctly", () => { + expect(xlmToStroops("1.5")).toBe(15_000_000n); + expect(xlmToStroops("0.5")).toBe(5_000_000n); + }); + + it("converts number input correctly", () => { + expect(xlmToStroops(1)).toBe(10_000_000n); + expect(xlmToStroops(0)).toBe(0n); + }); + + it("rounds down fractional stroops to the nearest stroop", () => { + // 0.00000015 XLM would be 1.5 stroops, should round down to 1 + expect(xlmToStroops("0.00000015")).toBe(1n); + }); }); describe("stroopsToXlm / xlmToStroops round-trip", () => { - it("round-trips correctly for whole XLM amounts", () => { - const xlmAmounts = ["0", "1", "100", "10000", "100000"]; - - for (const xlm of xlmAmounts) { - const stroops = xlmToStroops(xlm); - const backToXlm = stroopsToXlm(stroops); - expect(backToXlm).toBe(new Decimal(xlm).toFixed(7)); - } - }); - - it("round-trips correctly for common stroop amounts", () => { - const stroopAmounts = [0n, 1n, 10n, 100n, 1000n, 10_000_000n, 1_000_000_000_000n]; - - for (const stroops of stroopAmounts) { - const xlm = stroopsToXlm(stroops); - const backToStroops = xlmToStroops(xlm); - expect(backToStroops).toBe(stroops); - } - }); - - it("round-trip is accurate for values that could be affected by floating point", () => { - // These values are problematic with regular JS floating point math - const testValues = [ - "0.1", - "0.2", - "0.3", - "0.7", - "1.0000001", - "999999.9999999", - "1234.5678901", - ]; - - for (const xlm of testValues) { - const stroops = xlmToStroops(xlm); - const backToXlm = stroopsToXlm(stroops); - expect(backToXlm).toBe(new Decimal(xlm).toFixed(7)); - } - }); -}); \ No newline at end of file + it("round-trips correctly for whole XLM amounts", () => { + const xlmAmounts = ["0", "1", "100", "10000", "100000"]; + + for (const xlm of xlmAmounts) { + const stroops = xlmToStroops(xlm); + const backToXlm = stroopsToXlm(stroops); + expect(backToXlm).toBe(new Decimal(xlm).toFixed(7)); + } + }); + + it("round-trips correctly for common stroop amounts", () => { + const stroopAmounts = [0n, 1n, 10n, 100n, 1000n, 10_000_000n, 1_000_000_000_000n]; + + for (const stroops of stroopAmounts) { + const xlm = stroopsToXlm(stroops); + const backToStroops = xlmToStroops(xlm); + expect(backToStroops).toBe(stroops); + } + }); + + it("round-trip is accurate for values that could be affected by floating point", () => { + // These values are problematic with regular JS floating point math + const testValues = ["0.1", "0.2", "0.3", "0.7", "1.0000001", "999999.9999999", "1234.5678901"]; + + for (const xlm of testValues) { + const stroops = xlmToStroops(xlm); + const backToXlm = stroopsToXlm(stroops); + expect(backToXlm).toBe(new Decimal(xlm).toFixed(7)); + } + }); +}); diff --git a/tests/unit/utils/discount-calculator.utils.test.ts b/tests/unit/utils/discount-calculator.utils.test.ts index 542ea43..c118de1 100644 --- a/tests/unit/utils/discount-calculator.utils.test.ts +++ b/tests/unit/utils/discount-calculator.utils.test.ts @@ -83,7 +83,7 @@ describe("discount-calculator.utils", () => { faceValue: "-100", dueDate: new Date(), discountBps: 100, - }), + }) ).toThrow("Face value must be a positive number greater than zero"); expect(() => @@ -91,7 +91,7 @@ describe("discount-calculator.utils", () => { faceValue: "1000", dueDate: new Date(), discountBps: 12000, - }), + }) ).toThrow("Discount BPS must be between 0 and 10,000"); }); }); diff --git a/tests/unit/utils/invoice-state-machine.test.ts b/tests/unit/utils/invoice-state-machine.test.ts index 15c9ee8..67c28e3 100644 --- a/tests/unit/utils/invoice-state-machine.test.ts +++ b/tests/unit/utils/invoice-state-machine.test.ts @@ -22,15 +22,11 @@ describe("isValidInvoiceStateTransition", () => { }); it("rejects transition from DRAFT to SETTLED", () => { - expect(isValidInvoiceStateTransition(InvoiceStatus.DRAFT, InvoiceStatus.SETTLED)).toBe( - false - ); + expect(isValidInvoiceStateTransition(InvoiceStatus.DRAFT, InvoiceStatus.SETTLED)).toBe(false); }); it("rejects transition from DRAFT to PENDING", () => { - expect(isValidInvoiceStateTransition(InvoiceStatus.DRAFT, InvoiceStatus.PENDING)).toBe( - false - ); + expect(isValidInvoiceStateTransition(InvoiceStatus.DRAFT, InvoiceStatus.PENDING)).toBe(false); }); it("rejects transition from DRAFT to DRAFT", () => { @@ -52,9 +48,7 @@ describe("isValidInvoiceStateTransition", () => { }); it("rejects transition from PENDING to DRAFT", () => { - expect(isValidInvoiceStateTransition(InvoiceStatus.PENDING, InvoiceStatus.DRAFT)).toBe( - false - ); + expect(isValidInvoiceStateTransition(InvoiceStatus.PENDING, InvoiceStatus.DRAFT)).toBe(false); }); it("rejects transition from PENDING to FUNDED", () => { @@ -98,9 +92,7 @@ describe("isValidInvoiceStateTransition", () => { describe("valid transitions from FUNDED", () => { it("allows transition from FUNDED to SETTLED", () => { - expect(isValidInvoiceStateTransition(InvoiceStatus.FUNDED, InvoiceStatus.SETTLED)).toBe( - true - ); + expect(isValidInvoiceStateTransition(InvoiceStatus.FUNDED, InvoiceStatus.SETTLED)).toBe(true); }); it("allows transition from FUNDED to CANCELLED", () => { @@ -134,9 +126,7 @@ describe("isValidInvoiceStateTransition", () => { }); it("rejects transition from SETTLED to DRAFT", () => { - expect(isValidInvoiceStateTransition(InvoiceStatus.SETTLED, InvoiceStatus.DRAFT)).toBe( - false - ); + expect(isValidInvoiceStateTransition(InvoiceStatus.SETTLED, InvoiceStatus.DRAFT)).toBe(false); }); it("rejects transition from SETTLED to PENDING", () => { @@ -167,9 +157,7 @@ describe("isValidInvoiceStateTransition", () => { describe("valid transitions from CANCELLED", () => { it("rejects all transitions from CANCELLED", () => { allStatuses.forEach((status) => { - expect( - isValidInvoiceStateTransition(InvoiceStatus.CANCELLED, status) - ).toBe(false); + expect(isValidInvoiceStateTransition(InvoiceStatus.CANCELLED, status)).toBe(false); }); }); }); @@ -188,9 +176,7 @@ describe("isValidInvoiceStateTransition", () => { }); it("rejects transition from FUNDED to FUNDED", () => { - expect(isValidInvoiceStateTransition(InvoiceStatus.FUNDED, InvoiceStatus.FUNDED)).toBe( - false - ); + expect(isValidInvoiceStateTransition(InvoiceStatus.FUNDED, InvoiceStatus.FUNDED)).toBe(false); }); it("rejects transition from CANCELLED to CANCELLED", () => { diff --git a/tests/unit/utils/stellar-address.test.ts b/tests/unit/utils/stellar-address.test.ts index 196b7ea..ab21b2a 100644 --- a/tests/unit/utils/stellar-address.test.ts +++ b/tests/unit/utils/stellar-address.test.ts @@ -1,4 +1,7 @@ -import { isValidStellarPublicKey, isValidSorobanContractId } from "../../../src/utils/stellar-address.utils"; +import { + isValidStellarPublicKey, + isValidSorobanContractId, +} from "../../../src/utils/stellar-address.utils"; describe("stellar-address utils", () => { describe("isValidStellarPublicKey", () => { @@ -48,9 +51,9 @@ describe("stellar-address utils", () => { it("rejects malformed contract addresses", () => { expect(isValidSorobanContractId("C" + "0".repeat(55))).toBe(false); - expect(isValidSorobanContractId("CAX62CGE4JWSCDDO6NFUTC2V7VWGX6VNWC6EIB2BPKFYI2YEO5TV5WU")).toBe( - false - ); + expect( + isValidSorobanContractId("CAX62CGE4JWSCDDO6NFUTC2V7VWGX6VNWC6EIB2BPKFYI2YEO5TV5WU") + ).toBe(false); }); }); }); diff --git a/tests/unit/webhook-signature-headers.test.ts b/tests/unit/webhook-signature-headers.test.ts index cabe77f..bf15ef9 100644 --- a/tests/unit/webhook-signature-headers.test.ts +++ b/tests/unit/webhook-signature-headers.test.ts @@ -73,7 +73,7 @@ describe("verifyWebhookSignatureHeaders", () => { timestamp: String(NOW_MS), secret: SECRET, now, - }), + }) ).toBe(String(NOW_MS)); }); }); @@ -89,7 +89,7 @@ describe("verifyWebhookSignatureHeaders", () => { secret: SECRET, now, }), - "INVALID_SIGNATURE", + "INVALID_SIGNATURE" ); }); @@ -105,12 +105,16 @@ describe("verifyWebhookSignatureHeaders", () => { secret: SECRET, now, }), - "INVALID_SIGNATURE", + "INVALID_SIGNATURE" ); }); it("rejects a signature produced with the wrong secret", () => { - const wrongSig = computeWebhookSignatureForTimestamp(PAYLOAD, String(NOW_MS), "different-secret"); + const wrongSig = computeWebhookSignatureForTimestamp( + PAYLOAD, + String(NOW_MS), + "different-secret" + ); expectWebhookError( () => @@ -121,7 +125,7 @@ describe("verifyWebhookSignatureHeaders", () => { secret: SECRET, now, }), - "INVALID_SIGNATURE", + "INVALID_SIGNATURE" ); }); @@ -137,7 +141,7 @@ describe("verifyWebhookSignatureHeaders", () => { secret: SECRET, now, }), - "INVALID_SIGNATURE", + "INVALID_SIGNATURE" ); }); }); @@ -153,7 +157,7 @@ describe("verifyWebhookSignatureHeaders", () => { secret: SECRET, now, }), - "MISSING_SIGNATURE", + "MISSING_SIGNATURE" ); }); @@ -167,7 +171,7 @@ describe("verifyWebhookSignatureHeaders", () => { secret: SECRET, now, }), - "MISSING_SIGNATURE", + "MISSING_SIGNATURE" ); }); @@ -182,7 +186,7 @@ describe("verifyWebhookSignatureHeaders", () => { secret: SECRET, now, }), - "MISSING_SIGNATURE", + "MISSING_SIGNATURE" ); } }); @@ -198,7 +202,7 @@ describe("verifyWebhookSignatureHeaders", () => { secret: SECRET, now, }), - "MISSING_TIMESTAMP", + "MISSING_TIMESTAMP" ); } }); @@ -215,7 +219,7 @@ describe("verifyWebhookSignatureHeaders", () => { secret: SECRET, now, }), - "MALFORMED_SIGNATURE", + "MALFORMED_SIGNATURE" ); }); @@ -229,7 +233,7 @@ describe("verifyWebhookSignatureHeaders", () => { secret: SECRET, now, }), - "MALFORMED_SIGNATURE", + "MALFORMED_SIGNATURE" ); }); @@ -243,7 +247,7 @@ describe("verifyWebhookSignatureHeaders", () => { secret: SECRET, now, }), - "TIMESTAMP_OUT_OF_RANGE", + "TIMESTAMP_OUT_OF_RANGE" ); }); @@ -259,7 +263,7 @@ describe("verifyWebhookSignatureHeaders", () => { secret: SECRET, now, }), - "TIMESTAMP_SKEWED", + "TIMESTAMP_SKEWED" ); }); @@ -275,7 +279,7 @@ describe("verifyWebhookSignatureHeaders", () => { secret: SECRET, now, }), - "TIMESTAMP_SKEWED", + "TIMESTAMP_SKEWED" ); }); }); @@ -292,7 +296,7 @@ describe("verifyWebhookSignatureHeaders", () => { secret: SECRET, maxTimestampSkewMs: 5_000, now, - }), + }) ).not.toThrow(); const outsideWindow = NOW_MS - 10_000; @@ -307,7 +311,7 @@ describe("verifyWebhookSignatureHeaders", () => { maxTimestampSkewMs: 5_000, now, }), - "TIMESTAMP_SKEWED", + "TIMESTAMP_SKEWED" ); }); }); diff --git a/tests/unit/webhook-signature.test.ts b/tests/unit/webhook-signature.test.ts index 29571f9..f009654 100644 --- a/tests/unit/webhook-signature.test.ts +++ b/tests/unit/webhook-signature.test.ts @@ -1,7 +1,4 @@ -import { - computeWebhookSignature, - verifyWebhookSignature, -} from "../../src/utils/webhook-signature"; +import { computeWebhookSignature, verifyWebhookSignature } from "../../src/utils/webhook-signature"; describe("verifyWebhookSignature", () => { const SECRET_A = "whsec_test_secret_a_12345"; @@ -29,9 +26,13 @@ describe("verifyWebhookSignature", () => { }); it("should return false for empty inputs", () => { - expect(verifyWebhookSignature("", computeWebhookSignature(PAYLOAD, SECRET_A), SECRET_A)).toBe(false); + expect(verifyWebhookSignature("", computeWebhookSignature(PAYLOAD, SECRET_A), SECRET_A)).toBe( + false + ); expect(verifyWebhookSignature(PAYLOAD, "", SECRET_A)).toBe(false); - expect(verifyWebhookSignature(PAYLOAD, computeWebhookSignature(PAYLOAD, SECRET_A), "")).toBe(false); + expect(verifyWebhookSignature(PAYLOAD, computeWebhookSignature(PAYLOAD, SECRET_A), "")).toBe( + false + ); }); it("should never throw an exception", () => { diff --git a/tests/validate-invoice-for-publish.test.ts b/tests/validate-invoice-for-publish.test.ts index 0a5f239..157d11d 100644 --- a/tests/validate-invoice-for-publish.test.ts +++ b/tests/validate-invoice-for-publish.test.ts @@ -97,7 +97,7 @@ describe("validateInvoiceForPublish", () => { const errors = validateInvoiceForPublish(invoice); expect(errors).toHaveLength(3); expect(errors.map((e) => e.code)).toEqual( - expect.arrayContaining(["FACE_VALUE_TOO_LOW", "DUE_DATE_IN_PAST", "MISSING_DOCUMENT"]), + expect.arrayContaining(["FACE_VALUE_TOO_LOW", "DUE_DATE_IN_PAST", "MISSING_DOCUMENT"]) ); }); @@ -131,4 +131,4 @@ describe("validateInvoiceForPublish", () => { const errorsAgain = validateInvoiceForPublish(fullyInvalidInvoice); expect(errorsAgain).toEqual(errors); }); -}); \ No newline at end of file +}); diff --git a/tests/verify-payment.idempotency.test.ts b/tests/verify-payment.idempotency.test.ts index 2468ce2..c9039d8 100644 --- a/tests/verify-payment.idempotency.test.ts +++ b/tests/verify-payment.idempotency.test.ts @@ -236,7 +236,7 @@ describe("VerifyPaymentService idempotency (transaction hash as dedup key)", () expect(context.transactions.get(investmentA.id)).toHaveLength(1); expect(context.transactions.get(investmentB.id)).toHaveLength(1); expect(context.transactions.get(investmentA.id)?.[0].id).not.toBe( - context.transactions.get(investmentB.id)?.[0].id, + context.transactions.get(investmentB.id)?.[0].id ); }); }); diff --git a/tests/verify-payment.service.test.ts b/tests/verify-payment.service.test.ts index cfb3eb9..dbed36c 100644 --- a/tests/verify-payment.service.test.ts +++ b/tests/verify-payment.service.test.ts @@ -128,7 +128,7 @@ describe("VerifyPaymentService", () => { ok: true, status: 200, body: { successful: true }, - }), + }) ) .mockResolvedValueOnce( createMockResponse({ @@ -140,15 +140,14 @@ describe("VerifyPaymentService", () => { { type: "payment", asset_code: "USDC", - asset_issuer: - "GDUKMGUGDZQK6YHZZ7KQJX2BQPJYVY5W7C2D4GMXQ3MNK4V2ZXN5R4OT", + asset_issuer: "GDUKMGUGDZQK6YHZZ7KQJX2BQPJYVY5W7C2D4GMXQ3MNK4V2ZXN5R4OT", amount: "100.0000", to: "GCFXROWPUBKEYEXAMPLE7KQJX2BQPJYVY5W7C2D4GMXQ3MNK4V2ZXNOPE", }, ], }, }, - }), + }) ); const result = await context.service.verifyPayment({ @@ -158,9 +157,7 @@ describe("VerifyPaymentService", () => { expect(result.outcome).toBe("verified"); expect(result.status).toBe(InvestmentStatus.CONFIRMED); - expect(context.investmentStore.get(context.investment.id)?.transactionHash).toBe( - stellarTxHash, - ); + expect(context.investmentStore.get(context.investment.id)?.transactionHash).toBe(stellarTxHash); const savedTransactions = context.transactions.get(context.investment.id) ?? []; expect(savedTransactions).toHaveLength(1); @@ -169,7 +166,6 @@ describe("VerifyPaymentService", () => { expect(savedTransactions[0].invoiceId).toBe(context.investment.invoiceId); - const secondResult = await context.service.verifyPayment({ investmentId: context.investment.id, stellarTxHash, @@ -189,14 +185,14 @@ describe("VerifyPaymentService", () => { ok: false, status: 503, body: {}, - }), + }) ) .mockResolvedValueOnce( createMockResponse({ ok: true, status: 200, body: { successful: true }, - }), + }) ) .mockResolvedValueOnce( createMockResponse({ @@ -208,15 +204,14 @@ describe("VerifyPaymentService", () => { { type: "payment", asset_code: "USDC", - asset_issuer: - "GDUKMGUGDZQK6YHZZ7KQJX2BQPJYVY5W7C2D4GMXQ3MNK4V2ZXN5R4OT", + asset_issuer: "GDUKMGUGDZQK6YHZZ7KQJX2BQPJYVY5W7C2D4GMXQ3MNK4V2ZXN5R4OT", amount: "100.0000", to: "GCFXROWPUBKEYEXAMPLE7KQJX2BQPJYVY5W7C2D4GMXQ3MNK4V2ZXNOPE", }, ], }, }, - }), + }) ); const result = await context.service.verifyPayment({ @@ -238,14 +233,14 @@ describe("VerifyPaymentService", () => { ok: false, status: 404, body: {}, - }), + }) ); await expect( context.service.verifyPayment({ investmentId: context.investment.id, stellarTxHash: "missing-hash", - }), + }) ).rejects.toMatchObject({ code: "transaction_not_found", statusCode: 404, @@ -261,7 +256,7 @@ describe("VerifyPaymentService", () => { ok: true, status: 200, body: { successful: true }, - }), + }) ) .mockResolvedValueOnce( createMockResponse({ @@ -279,14 +274,14 @@ describe("VerifyPaymentService", () => { ], }, }, - }), + }) ); await expect( context.service.verifyPayment({ investmentId: context.investment.id, stellarTxHash: "bad-payment", - }), + }) ).rejects.toMatchObject({ code: "invalid_payment", statusCode: 422, diff --git a/tests/webhook-dispatcher.service.test.ts b/tests/webhook-dispatcher.service.test.ts index 3fdccc9..e7aab7a 100644 --- a/tests/webhook-dispatcher.service.test.ts +++ b/tests/webhook-dispatcher.service.test.ts @@ -1,27 +1,55 @@ -import { WebhookDispatcherService, generateWebhookSignature } from "../src/services/webhook-dispatcher.service"; +import { + WebhookDispatcherService, + generateWebhookSignature, +} from "../src/services/webhook-dispatcher.service"; import { WebhookSubscription } from "../src/models/WebhookSubscription.model"; import { WebhookDeliveryLog } from "../src/models/WebhookDeliveryLog.model"; describe("WebhookDispatcherService", () => { - const subscription = { id: "sub-1", url: "https://example.test/hook", secret: "secret", eventTypes: ["invoice.published"], active: true } as WebhookSubscription; + const subscription = { + id: "sub-1", + url: "https://example.test/hook", + secret: "secret", + eventTypes: ["invoice.published"], + active: true, + } as WebhookSubscription; const log = { save: jest.fn().mockResolvedValue(undefined) }; - const dataSource = { getRepository: jest.fn((entity) => entity === WebhookSubscription ? { find: jest.fn().mockResolvedValue([subscription]) } : log) }; + const dataSource = { + getRepository: jest.fn((entity) => + entity === WebhookSubscription ? { find: jest.fn().mockResolvedValue([subscription]) } : log + ), + }; afterEach(() => jest.restoreAllMocks()); - it("generates a deterministic HMAC signature", () => expect(generateWebhookSignature("payload", "secret")).toBe("b82fcb791acec57859b989b430a826488ce2e479fdf92326bd0a2e8375a42ba4")); + it("generates a deterministic HMAC signature", () => + expect(generateWebhookSignature("payload", "secret")).toBe( + "b82fcb791acec57859b989b430a826488ce2e479fdf92326bd0a2e8375a42ba4" + )); it("posts signed event payloads and records delivery", async () => { global.fetch = jest.fn().mockResolvedValue({ status: 202 }) as any; - const result = await new WebhookDispatcherService(dataSource as any).dispatchWebhookEvent("invoice.published", { id: "invoice-1" }); + const result = await new WebhookDispatcherService(dataSource as any).dispatchWebhookEvent( + "invoice.published", + { id: "invoice-1" } + ); expect(result[0]).toMatchObject({ delivered: true, attempts: 1, responseStatus: 202 }); - expect(global.fetch).toHaveBeenCalledWith(subscription.url, expect.objectContaining({ method: "POST", headers: expect.objectContaining({ "x-signature": expect.any(String) }) })); + expect(global.fetch).toHaveBeenCalledWith( + subscription.url, + expect.objectContaining({ + method: "POST", + headers: expect.objectContaining({ "x-signature": expect.any(String) }), + }) + ); expect(log.save).toHaveBeenCalledWith(expect.objectContaining({ delivered: true })); }); it("retries failed responses three times", async () => { global.fetch = jest.fn().mockResolvedValue({ status: 500 }) as any; - const result = await new WebhookDispatcherService(dataSource as any).dispatchWebhookEvent("invoice.published", {}); + const result = await new WebhookDispatcherService(dataSource as any).dispatchWebhookEvent( + "invoice.published", + {} + ); expect(result[0]).toMatchObject({ delivered: false, attempts: 3, responseStatus: 500 }); expect(global.fetch).toHaveBeenCalledTimes(3); }); From 7bb82d515a43423d9a6d07e0ec8748059f5c8690 Mon Sep 17 00:00:00 2001 From: Skinny001 Date: Sun, 30 Aug 2026 02:37:47 +0100 Subject: [PATCH 2/2] fix: add rejectInvoice method and fix pre-existing build issues - Added rejectInvoice method to InvoiceService with proper status transitions - Fixed duplicate logger import in data-source.ts - Added rpcUrl to test config in full-flow.e2e.test.ts - Added INVOICE_REJECTED to InvoiceTransitionReason and NotificationType enums - Fixed admin-invoice-reject test to properly set up seller relation Build, format, lint all pass. --- src/config/data-source.ts | 1 - src/lib/invoice-lifecycle-log.ts | 3 +- src/services/invoice.service.ts | 61 +++++++++++++++++++ src/types/enums.ts | 1 + tests/e2e/full-flow.e2e.test.ts | 1 + .../admin-invoice-reject.integration.test.ts | 2 +- 6 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/config/data-source.ts b/src/config/data-source.ts index 4f982cb..4a210e0 100644 --- a/src/config/data-source.ts +++ b/src/config/data-source.ts @@ -11,7 +11,6 @@ */ import { logger } from "../observability/logger"; import dataSource from "./database"; -import { logger } from "../observability/logger"; // Validate dataSource is properly initialized if (!dataSource) { diff --git a/src/lib/invoice-lifecycle-log.ts b/src/lib/invoice-lifecycle-log.ts index d1d7e97..2693cf9 100644 --- a/src/lib/invoice-lifecycle-log.ts +++ b/src/lib/invoice-lifecycle-log.ts @@ -6,7 +6,8 @@ export type InvoiceTransitionReason = | "seller_published" | "seller_batch_published" | "fully_funded" - | "admin_settled"; + | "admin_settled" + | "admin_rejected"; export interface InvoiceTransitionLogInput { invoiceId: string; diff --git a/src/services/invoice.service.ts b/src/services/invoice.service.ts index 7cf3d50..dde196a 100644 --- a/src/services/invoice.service.ts +++ b/src/services/invoice.service.ts @@ -491,6 +491,67 @@ export class InvoiceService { return this.toDTO(updated); } + /** + * Reject a pending invoice (admin action) + */ + async rejectInvoice(input: { invoiceId: string; rejectionReason: string }): Promise { + const invoice = await this.invoiceRepository.findOne({ + where: { id: input.invoiceId }, + relations: ["seller"], + }); + + if (!invoice) { + throw new ServiceError("invoice_not_found", "Invoice not found", 404); + } + + // Check if already rejected + if (invoice.status === InvoiceStatus.REJECTED) { + throw new ServiceError("invoice_already_rejected", "Invoice is already rejected", 409); + } + + // Check if transition is valid + if (!this.isValidTransition(invoice.status, InvoiceStatus.REJECTED)) { + throw new ServiceError( + "invalid_status_transition", + `Cannot transition from ${invoice.status} to ${InvoiceStatus.REJECTED}`, + 409 + ); + } + + const previousStatus = invoice.status; + invoice.status = InvoiceStatus.REJECTED; + invoice.rejectionReason = input.rejectionReason.trim(); + const updated = await this.invoiceRepository.save(invoice); + + const seller = invoice.seller as unknown as User; + logInvoiceTransition(logger, { + invoiceId: updated.id, + fromState: previousStatus, + toState: InvoiceStatus.REJECTED, + actorWallet: seller?.stellarAddress ?? "admin", + reason: "admin_rejected", + }); + + // Notify seller if notification sink is available + if (this.notificationSink && seller) { + try { + await this.notificationSink.createNotification( + seller.id, + NotificationType.INVOICE, + "Invoice Rejected", + `Your invoice ${invoice.invoiceNumber} has been rejected: ${input.rejectionReason}` + ); + } catch (notifyError) { + logger.warn("Failed to notify seller of invoice rejection", { + error: notifyError, + invoiceId: invoice.id, + }); + } + } + + return this.toDTO(updated); + } + /** * Publish several draft invoices in one atomic step. * diff --git a/src/types/enums.ts b/src/types/enums.ts index 7b403b0..a1d707b 100644 --- a/src/types/enums.ts +++ b/src/types/enums.ts @@ -57,4 +57,5 @@ export enum NotificationType { PAYMENT = "payment", KYC = "kyc", SYSTEM = "system", + INVOICE_REJECTED = "invoice_rejected", } diff --git a/tests/e2e/full-flow.e2e.test.ts b/tests/e2e/full-flow.e2e.test.ts index 28691a7..66dc4e0 100644 --- a/tests/e2e/full-flow.e2e.test.ts +++ b/tests/e2e/full-flow.e2e.test.ts @@ -148,6 +148,7 @@ describe("E2E: Complete Invoice Financing Flow", () => { enabled: false, contractId: null, fundingMode: "wallet_xdr", + rpcUrl: null, }, ipfs: { apiUrl: "https://api.pinata.cloud", diff --git a/tests/integration/admin-invoice-reject.integration.test.ts b/tests/integration/admin-invoice-reject.integration.test.ts index 58f731d..dcf4e80 100644 --- a/tests/integration/admin-invoice-reject.integration.test.ts +++ b/tests/integration/admin-invoice-reject.integration.test.ts @@ -119,7 +119,7 @@ function seedPendingInvoice(repo: InMemoryInvoiceRepository, sellerId: string): createdAt: now, updatedAt: now, deletedAt: null, - seller: undefined as unknown as Invoice["seller"], + seller: { id: sellerId, stellarAddress: "GTEST" } as unknown as Invoice["seller"], investments: [], transactions: [], } as Invoice;