From 0b83187d0dc102cd1f8029f1184a237b5a35d180 Mon Sep 17 00:00:00 2001 From: LaGodxy Date: Tue, 21 Apr 2026 16:51:53 -0700 Subject: [PATCH 1/2] Migration --- .env.csp.example | 108 - .env.development | 60 - .env.example | 86 +- .env.production | 28 - .env.staging | 28 - .eslintrc.js | 58 - .github/workflows/ci.yml | 485 +- .gitignore | 202 +- .npmrc | 2 - .prettierignore | 40 - .prettierrc | 14 - COMPRESSION_PR_DESCRIPTION.md | 246 - Dockerfile | 55 - GITHUB_PR_DESCRIPTION.md | 241 - PR_DESCRIPTION.md | 252 - README.md | 173 + TESTING_IMPLEMENTATION.md | 296 - TYPE_SAFETY_PR.md | 162 - admin.controller.ts | 30 - admin.guard.ts | 20 - admin.module.ts | 16 - admin.service.ts | 103 - benchmarks/chains/README.md | 351 - benchmarks/chains/benchmark-reporter.ts | 377 - benchmarks/chains/benchmark-runner.ts | 123 - benchmarks/chains/index.ts | 13 - benchmarks/chains/run-benchmarks.ts | 176 - benchmarks/chains/stacks/auth.stack.ts | 43 - benchmarks/chains/stacks/full.stack.ts | 55 - benchmarks/chains/stacks/minimal.stack.ts | 38 - benchmarks/chains/types/benchmark-types.ts | 210 - .../chains/utils/performance-measurer.ts | 132 - benchmarks/memory/README.md | 42 - benchmarks/memory/heap-snapshot.ts | 25 - benchmarks/memory/run-memory-profile.ts | 231 - benchmarks/memory/scenarios.ts | 72 - build_output.txt | Bin 33694 -> 0 bytes build_output_2.txt | Bin 17746 -> 0 bytes claims.e2e-spec.ts | 131 - dashboard.dto.ts | 42 - docker-compose.yml | 96 - docs/API_SECURITY_GUIDE.md | 564 - docs/API_VERSIONING.md | 255 - docs/CSP_IMPLEMENTATION.md | 511 - docs/DATABASE_OPTIMIZATION_GUIDE.md | 497 - docs/DATABASE_SCHEMA.md | 365 - docs/DEVELOPER_GUIDE.md | 134 - docs/EMAIL_COMMUNICATION_GUIDE.md | 534 - docs/ENVIRONMENT_VARIABLES.md | 158 - docs/ERROR_HANDLING_GUIDE.md | 571 - docs/LOAD_TESTING.md | 44 - docs/MODULE_ORGANIZATION_GUIDE.md | 465 - docs/PERFORMANCE.md | 535 - docs/RATE_LIMITING_IMPLEMENTATION.md | 283 - docs/SERVICE_LAYER_ARCHITECTURE.md | 28 - docs/ZERO_DOWNTIME_MIGRATIONS.md | 59 - docs/enhanced-rate-limiting.md | 260 - docs/health-checks.md | 300 - docs/observability.md | 374 - docs/properties-api.md | 189 - docs/testing.md | 301 - docs/valuation-api.md | 250 - eslint.config.js | 29 - indexer-monitor.service.ts | 321 - jest.config.js | 40 +- junit.xml | 953 - loadtests/propchain-loadtest.js | 24 - monitoring.module.ts | 51 - nest-cli.json | 33 +- package-lock.json | 23491 ++++------------ package.json | 181 +- prisma/schema.prisma | 880 +- pw_test_out.txt | 205 - reputation.module.ts | 13 - reputation.service.ts | 47 - scripts/backup.sh | 115 - scripts/init-db.sql | 165 - scripts/loadtest-ci.sh | 22 - scripts/restore.sh | 134 - scripts/rollback-migration.js | 89 - scripts/run-comprehensive-tests.ts | 164 - scripts/test-restore.sh | 115 - scripts/validate-migrations.js | 123 - src/analytics/EventAggregator.ts | 57 - src/analytics/MetricsCalculator.ts | 56 - src/analytics/StreamProcessor.ts | 63 - src/analytics/analytics.module.ts | 11 - src/api-keys/README.md | 368 - src/api-keys/SETUP.md | 249 - src/api-keys/api-key-analytics.service.ts | 281 - src/api-keys/api-key-rotation.scheduler.ts | 105 - src/api-keys/api-key.controller.ts | 215 - src/api-keys/api-key.module.ts | 12 - src/api-keys/api-key.service.ts | 535 - src/api-keys/api-key.types.ts | 92 - src/api-keys/api-keys.module.ts | 18 - src/api-keys/dto/api-key-query.dto.ts | 18 - src/api-keys/dto/api-key-response.dto.ts | 47 - src/api-keys/dto/create-api-key.dto.ts | 36 - src/api-keys/dto/index.ts | 4 - src/api-keys/dto/update-api-key.dto.ts | 37 - src/api-keys/enums/api-key-scope.enum.ts | 7 - .../properties-with-api-keys.example.ts | 138 - src/app.ci.module.ts | 24 - src/app.controller.ts | 17 + src/app.module.ts | 221 +- src/audit/AuditLogger.ts | 74 - src/audit/ComplianceManager.ts | 92 - src/audit/ForensicAnalyzer.ts | 73 - src/audit/audit.controller.ts | 47 - src/audit/audit.module.ts | 29 - src/audit/audit.service.ts | 157 - src/audit/entities/audit-log.entity.ts | 58 - src/audit/interceptors/audit.interceptor.ts | 52 - src/auth/OAuth2Provider.ts | 424 - src/auth/SAMLProvider.ts | 513 - src/auth/SocialAuth.ts | 664 - src/auth/auth.controller.ts | 456 - src/auth/auth.module.ts | 58 - src/auth/auth.service.ts | 644 - src/auth/auth.types.ts | 124 - src/auth/constants.ts | 20 - src/auth/decorators/roles.decorator.ts | 4 - src/auth/dto/auth-response.dto.ts | 139 - src/auth/dto/forgot-password.dto.ts | 12 - src/auth/dto/index.ts | 6 - src/auth/dto/login.dto.ts | 88 - src/auth/dto/refresh-token.dto.ts | 13 - src/auth/dto/reset-password.dto.ts | 25 - src/auth/dto/verify-email-params.dto.ts | 12 - src/auth/guards/jwt-auth.guard.ts | 38 - src/auth/guards/local-auth.guard.ts | 5 - src/auth/guards/login-attempts.guard.ts | 99 - src/auth/guards/rbac.guard.ts | 47 - src/auth/guards/throttle-auth.guard.ts | 9 - src/auth/guards/wallet-signature.guard.ts | 39 - src/auth/interceptors/security.interceptor.ts | 33 - src/auth/mfa/index.ts | 3 - src/auth/mfa/mfa.controller.ts | 124 - src/auth/mfa/mfa.module.ts | 10 - src/auth/mfa/mfa.service.ts | 150 - src/auth/middleware/auth.middleware.ts | 23 - src/auth/strategies/jwt.strategy.ts | 42 - src/auth/strategies/local.strategy.ts | 32 - src/auth/strategies/web3.strategy.ts | 56 - src/auth/wallet-signature.service.ts | 123 - .../DISASTER_RECOVERY_RUNBOOK.md | 589 - src/backup-recovery/README.md | 333 - src/backup-recovery/SETUP_GUIDE.md | 558 - src/backup-recovery/backup-cli.ts | 321 - .../backup-monitoring.service.ts | 526 - .../backup-recovery.controller.ts | 259 - src/backup-recovery/backup-recovery.module.ts | 34 - .../backup-verification.service.ts | 591 - src/backup-recovery/backup.types.ts | 164 - .../database-backup.service.ts | 506 - .../disaster-recovery.service.ts | 703 - .../document-backup.service.ts | 499 - src/blockchain/blockchain.module.ts | 13 - src/blockchain/blockchain.service.ts | 96 - .../external-ledger-event.controller.ts | 146 - .../dto/external-ledger-event.dto.ts | 229 - src/blockchain/enums/supported-chain.enum.ts | 5 - .../guards/external-ledger-event.guard.ts | 63 - src/blockchain/providers/provider.factory.ts | 20 - .../providers/submit-puzzle.provider.ts | 72 - .../services/external-ledger-event.service.ts | 171 - .../stellar/stellar-optimization.service.ts | 346 - .../stellar/stellar-payout.controller.ts | 115 - .../stellar/stellar-payout.module.ts | 12 - .../stellar/stellar-payout.service.ts | 353 - src/blockchain/submit-puzzle.provider.spec.ts | 24 - .../tests/external-ledger-event.spec.ts | 298 - .../external-ledger-event.validator.spec.ts | 330 - .../external-ledger-event.validator.ts | 334 - src/blockchain/wallet/wallet.service.ts | 99 - src/cache/CacheManager.ts | 100 - src/cache/CacheWarmer.ts | 47 - src/cache/RedisCluster.ts | 77 - src/common/api-version/api-version.module.ts | 84 - src/common/api-version/constants.ts | 112 - src/common/api-version/exports.ts | 45 - .../api-version/guards/api-version.guard.ts | 138 - src/common/api-version/index.ts | 51 - .../interceptors/api-version.interceptor.ts | 247 - .../middleware/api-version.middleware.ts | 179 - .../services/api-version.service.ts | 291 - .../services/version-manager.service.ts | 265 - src/common/audit/audit.module.ts | 14 - .../cache/cache-invalidation.service.ts | 639 - src/common/cache/cache-warming.service.ts | 490 - src/common/cache/cache.module.ts | 32 - src/common/cache/multi-level-cache.service.ts | 528 - src/common/compliance/compliance.module.ts | 48 - src/common/controllers/audit.controller.ts | 257 - .../controllers/compliance.controller.ts | 405 - .../controllers/compression.controller.ts | 109 - .../decorators/api-key-scopes.decorator.ts | 3 - src/common/decorators/api-key.decorator.ts | 6 - .../duplicate-protection.decorator.ts | 10 - .../decorators/require-scopes.decorator.ts | 5 - src/common/dto/compliance.dto.ts | 389 - src/common/dto/date-range.dto.ts | 20 - src/common/dto/index.ts | 3 - src/common/dto/pagination.dto.ts | 31 - src/common/dto/sort.dto.ts | 21 - src/common/dtos/api-response.dto.ts | 129 - .../api-standard-error-response.decorator.ts | 17 - src/common/errors/custom.exceptions.ts | 171 - src/common/errors/error-formatter.service.ts | 198 - src/common/errors/error-handling.module.ts | 28 - src/common/errors/error.codes.ts | 139 - src/common/errors/error.dto.ts | 73 - src/common/errors/error.filter.spec.ts | 167 - src/common/errors/error.filter.ts | 238 - src/common/errors/error.types.ts | 105 - src/common/errors/exceptions.ts | 183 - src/common/errors/index.ts | 32 - src/common/errors/timeout.exceptions.ts | 46 - src/common/filters/all-exceptions.filter.ts | 100 - src/common/filters/global-exception.filter.ts | 364 - .../filters/validation-exception.filter.ts | 45 - src/common/guards/api-key.guard.ts | 127 - .../guards/duplicate-protection.guard.ts | 127 - src/common/guards/idempotency.guard.ts | 136 - src/common/interceptors/audit.interceptor.ts | 264 - .../interceptors/response.interceptor.ts | 51 - src/common/logger/correlation-id.ts | 10 - src/common/logger/logger.module.ts | 64 - src/common/logger/logger.service.ts | 131 - src/common/logger/logging.interceptor.ts | 40 - src/common/logger/logging.middleware.ts | 27 - src/common/logging/correlation-id.ts | 33 - .../logging/distributed-tracer.service.ts | 241 - src/common/logging/logger.service.ts | 183 - src/common/logging/logging.config.ts | 180 - src/common/logging/logging.interceptor.ts | 44 - src/common/logging/logging.middleware.ts | 20 - src/common/logging/logging.module.ts | 16 - .../middleware/payload-limit.middleware.ts | 11 - .../payload-validation.middleware.ts | 14 - .../request-size-limiter.middleware.ts | 52 - src/common/modules/compression.module.ts | 18 - src/common/pagination/PAGINATION.md | 354 - src/common/pagination/PAGINATION_GUIDE.md | 463 - .../pagination/cursor-pagination.dto.ts | 18 - src/common/pagination/index.ts | 2 - src/common/pagination/pagination.dto.ts | 163 - src/common/pagination/pagination.module.ts | 9 - src/common/pagination/pagination.service.ts | 133 - .../tests/pagination.integration.spec.ts | 175 - .../tests/pagination.performance.spec.ts | 230 - .../tests/pagination.service.spec.ts | 182 - src/common/patterns/dependency.injection.ts | 413 - src/common/patterns/import.export.patterns.ts | 429 - src/common/patterns/index.ts | 47 - .../patterns/module.organization.service.ts | 711 - src/common/patterns/module.structure.ts | 459 - src/common/services/audit.service.ts | 213 - src/common/services/base.service.ts | 45 - src/common/services/cache.service.ts | 1044 - .../services/compliance-reporting.service.ts | 564 - src/common/services/data-residency.service.ts | 428 - src/common/services/data-retention.service.ts | 428 - src/common/services/encryption.service.ts | 292 - src/common/services/gdpr.service.ts | 536 - src/common/services/idempotency.service.ts | 242 - src/common/services/kyc-aml.service.ts | 579 - .../services/password-rotation.service.ts | 239 - src/common/services/redis.config.ts | 20 - src/common/services/redis.constant.ts | 1 - src/common/services/redis.module.ts | 21 - src/common/services/redis.service.ts | 118 - src/common/tests/compression.spec.ts | 206 - .../tests/duplicate-protection.guard.spec.ts | 309 - src/common/tests/duplicate.validator.spec.ts | 349 - src/common/tests/idempotency.service.spec.ts | 296 - src/common/utils/resilence.util.ts | 39 - src/common/utils/timeout.util.ts | 57 - .../validation/boundary-validation.module.ts | 9 - .../validation/boundary-validation.service.ts | 75 - src/common/validation/index.ts | 2 - src/common/validators/duplicate.validator.ts | 440 - .../validators/file-upload.validator.ts | 307 - src/common/validators/index.ts | 2 - .../is-ethereum-address.validator.ts | 37 - .../is-strong-password.validator.ts | 44 - src/common/validators/password.validator.ts | 228 - .../validators/sql-injection.validator.ts | 119 - src/common/validators/validation.utils.ts | 395 - src/common/validators/xss.validator.ts | 106 - .../validators/year-not-future.validator.ts | 32 - .../automation/workflow.service.ts | 862 - src/communication/communication.module.ts | 121 - .../decorators/idempotent.decorator.ts | 10 - .../deliverability/deliverability.service.ts | 936 - src/communication/email/email.analytics.ts | 916 - .../email/email.delivery-tracking.ts | 394 - src/communication/email/email.queue.ts | 716 - src/communication/email/email.service.ts | 590 - src/communication/email/email.template.ts | 520 - src/communication/index.ts | 26 - .../interceptors/idempotency.interceptor.ts | 64 - .../jobs/background-job-monitoring.service.ts | 466 - .../jobs/background-jobs.controller.ts | 63 - .../jobs/email-queue.processor.ts | 137 - .../multichannel/multichannel.service.ts | 769 - .../preferences/preference.service.ts | 652 - .../background-job-monitoring.service.spec.ts | 324 - src/config/ConfigManager.ts | 114 - src/config/EnvironmentConfig.ts | 101 - src/config/FeatureFlags.ts | 83 - src/config/config.loader.ts | 137 - src/config/configuration.controller.ts | 34 - .../configuration.management.controller.ts | 465 - src/config/configuration.module.ts | 37 - src/config/configuration.service.ts | 367 - src/config/configuration.ts | 7 - .../interfaces/joi-schema-config.interface.ts | 100 - src/config/observability.config.ts | 89 - src/config/startup.validation.service.ts | 36 - src/config/storage-multicloud.config.ts | 115 - src/config/storage.config.ts | 52 - src/config/utils/config.audit.ts | 457 - src/config/utils/config.encryption.ts | 123 - src/config/utils/config.hot-reload.ts | 220 - src/config/utils/config.versioning.ts | 371 - src/config/utils/cors-origin.validator.ts | 131 - src/config/utils/env.sanitizer.ts | 94 - src/config/utils/env.testing.ts | 188 - src/config/utils/env.validator.ts | 366 - src/config/validation/config.validation.ts | 269 - src/config/valuation.config.ts | 45 - src/database/ConnectionPool.ts | 254 - src/database/QueryRouter.ts | 321 - src/database/ReplicaManager.ts | 204 - src/database/connection-health.service.ts | 17 - src/database/database.module.ts | 13 - src/database/index.ts | 3 - src/database/optimization/connection.pool.ts | 409 - .../database-optimization.controller.ts | 42 - .../optimization/index-monitor.service.ts | 100 - src/database/optimization/index.strategy.ts | 574 - src/database/optimization/index.ts | 41 - .../optimization/performance.monitor.ts | 472 - src/database/optimization/query.optimizer.ts | 415 - src/database/prisma.module.ts | 8 + src/database/prisma.service.ts | 13 + src/database/prisma/prisma.module.ts | 11 - src/database/prisma/prisma.service.ts | 193 - src/database/prisma/prisma.types.ts | 59 - .../prisma/transaction-manager.service.ts | 330 - src/database/retry-connection.ts | 18 - src/docs/DocumentationGenerator.ts | 296 - src/docs/ExampleGenerator.ts | 713 - src/docs/InteractiveTester.ts | 402 - src/documents/document.controller.ts | 204 - src/documents/document.model.ts | 82 - src/documents/document.service.ts | 528 - src/documents/documents.module.ts | 48 - src/documents/dto/document-query.dto.ts | 81 - src/documents/dto/document-response.dto.ts | 351 - src/documents/dto/download-query.dto.ts | 16 - src/documents/dto/index.ts | 5 - src/documents/dto/update-metadata.dto.ts | 84 - src/documents/dto/upload-document.dto.ts | 85 - .../document-upload.interceptor.ts | 27 - src/documents/storage/file-storage.service.ts | 30 - src/donations/donations.controller.ts | 45 - src/donations/donations.module.ts | 20 - src/donations/donations.service.ts | 209 - src/donations/dto/donation-webhook.dto.ts | 41 - src/errors/ErrorClassifier.ts | 142 - src/errors/IncidentResponder.ts | 61 - src/errors/RecoveryManager.ts | 76 - src/errors/errors.module.ts | 10 - .../tiered-rate-limit-usage.controller.ts | 77 - src/export/README.md | 247 - src/export/dto/export.dto.ts | 131 - src/export/export.controller.spec.ts | 176 - src/export/export.controller.ts | 283 - src/export/export.module.ts | 25 - src/export/export.processor.ts | 328 - src/export/export.service.ts | 280 - src/feature-flags/README.md | 336 - src/feature-flags/dto/feature-flag.dto.ts | 413 - .../feature-flag-analytics.service.ts | 298 - .../feature-flag-helper.service.ts | 219 - src/feature-flags/feature-flag.controller.ts | 187 - src/feature-flags/feature-flag.module.ts | 15 - src/feature-flags/feature-flag.service.ts | 561 - .../middleware/feature-flag.middleware.ts | 176 - .../models/feature-flag.entity.ts | 95 - src/files/files.controller.ts | 18 - src/files/files.module.ts | 4 - src/gateway/CircuitBreaker.ts | 142 - src/gateway/LoadBalancer.ts | 51 - src/gateway/ServiceRegistry.ts | 88 - src/gateway/gateway.controller.ts | 69 - src/gateway/gateway.module.ts | 12 - src/graphql/PersistedQueries.ts | 43 - src/graphql/QueryOptimizer.ts | 74 - src/graphql/ResponseCache.ts | 45 - src/health/health-analytics.service.ts | 123 - src/health/health-scheduler.service.ts | 167 - src/health/health.controller.ts | 209 - src/health/health.module.ts | 40 - src/health/indicators/blockchain.health.ts | 74 - src/health/indicators/cpu.health.ts | 57 - src/health/indicators/database.health.ts | 74 - src/health/indicators/dependencies.health.ts | 147 - src/health/indicators/disk.health.ts | 46 - src/health/indicators/memory.health.ts | 48 - src/health/indicators/redis.health.ts | 141 - src/i18n/en/errors.json | 38 - src/i18n/es/errors.json | 38 - src/jobs/FailureHandler.ts | 505 - src/jobs/JobManager.ts | 562 - src/jobs/QueueProcessor.ts | 514 - src/jobs/property-cleanup.service.ts | 130 - src/libs/errors.ts | 140 - src/libs/logger.ts | 104 - src/main.ci.ts | 12 - src/main.ts | 176 +- src/middleware/advanced/ARCHITECTURE.md | 449 - src/middleware/advanced/CHECKLIST.md | 436 - .../advanced/IMPLEMENTATION_SUMMARY.md | 435 - src/middleware/advanced/QUICKSTART.md | 281 - src/middleware/advanced/README.md | 416 - .../circuit-breaker.middleware.spec.ts | 429 - .../advanced/circuit-breaker.middleware.ts | 344 - src/middleware/advanced/index.ts | 17 - .../advanced/timeout.middleware.spec.ts | 214 - src/middleware/advanced/timeout.middleware.ts | 143 - src/middleware/advanced/usage-examples.ts | 299 - src/middleware/compression.middleware.ts | 185 - src/middleware/errorHandler.ts | 106 - src/models/AuditLog.ts | 44 - src/models/Configuration.ts | 31 - src/models/ErrorReport.ts | 48 - src/models/Job.ts | 265 - src/models/Notification.ts | 45 - src/models/api-key.entity.ts | 20 - src/models/document.entity.ts | 28 - src/models/donation.entity.ts | 19 - src/models/index.ts | 9 - src/models/permission.entity.ts | 11 - src/models/property.entity.ts | 37 - src/models/role.entity.ts | 11 - src/models/transaction.entity.ts | 31 - src/models/user.entity.ts | 52 - src/models/withdrawal.entity.ts | 11 - src/monitoring/indexer-monitor.controller.ts | 57 - .../tests/indexer-monitor.controller.spec.ts | 265 - .../tests/indexer-monitor.service.spec.ts | 321 - src/notifications/ChannelManager.ts | 58 - src/notifications/NotificationManager.ts | 105 - src/notifications/TemplateEngine.ts | 57 - src/observability/metrics.interceptor.ts | 173 - src/observability/observability.controller.ts | 83 - src/observability/observability.module.ts | 47 - src/observability/pagination.metrics.ts | 7 - src/observability/payload.metrics.ts | 7 - .../performance-monitor.service.ts | 433 - src/observability/tracing.service.ts | 144 - src/properties/dto/create-property.dto.ts | 245 - src/properties/dto/index.ts | 5 - src/properties/dto/property-extra.dto.ts | 48 - src/properties/dto/property-query.dto.ts | 159 - src/properties/dto/property-response.dto.ts | 246 - src/properties/dto/property-search.dto.ts | 59 - src/properties/dto/property.dto.ts | 139 + src/properties/dto/update-property.dto.ts | 4 - src/properties/entities/property.entity.ts | 1 - src/properties/properties-admin.controller.ts | 43 - src/properties/properties.controller.ts | 153 +- src/properties/properties.module.ts | 16 +- src/properties/properties.service.ts | 1049 +- .../search/property-search.service.ts | 134 - .../search/search-analytics.service.ts | 18 - src/puzzles/puzzles.controller.ts | 18 - src/puzzles/puzzles.repository.ts | 52 - src/puzzles/puzzles.service.ts | 16 - src/rbac/dto/assign-permissions.dto.ts | 12 - src/rbac/dto/assign-role.dto.ts | 17 - src/rbac/dto/create-permission.dto.ts | 23 - src/rbac/dto/create-role.dto.ts | 27 - src/rbac/dto/index.ts | 5 - src/rbac/dto/update-role.dto.ts | 4 - src/rbac/enums/action.enum.ts | 13 - src/rbac/enums/index.ts | 3 - src/rbac/enums/predefined-role.enum.ts | 15 - src/rbac/enums/resource.enum.ts | 13 - src/rbac/rbac.module.ts | 11 - src/rbac/rbac.service.ts | 368 - src/search/dto/search.dto.ts | 60 - .../entities/search-analytics.entity.ts | 28 - src/search/entities/search-cache.entity.ts | 29 - src/search/search.controller.spec.ts | 18 - src/search/search.controller.ts | 26 - src/search/search.module.ts | 14 - src/search/search.service.ts | 179 - src/security/CSPManager.ts | 640 - src/security/SecurityHeaders.ts | 494 - src/security/SecurityScanner.ts | 670 - src/security/api/abuse.detection.ts | 488 - src/security/api/auth.hardening.ts | 350 - src/security/api/index.ts | 28 - src/security/api/request.validation.ts | 62 - src/security/api/security.headers.ts | 66 - src/security/api/security.testing.ts | 789 - src/security/api/threat.detection.ts | 487 - src/security/config/csp.config.ts | 367 - src/security/config/multer.config.ts | 89 - .../controllers/csp-violation.controller.ts | 258 - .../rate-limit-analytics.controller.ts | 51 - .../user-tier-management.controller.ts | 102 - src/security/csp.module.ts | 30 - .../decorators/rate-limit.decorator.ts | 4 - .../sensitive-rate-limit.decorator.ts | 5 - .../decorators/tiered-rate-limit.decorator.ts | 90 - .../guards/advanced-rate-limit.guard.ts | 120 - .../sensitive-endpoint-rate-limit.guard.ts | 162 - src/security/middleware/csp.middleware.ts | 91 - .../header-validation.middleware.ts | 308 - .../middleware/rate-limit.middleware.ts | 153 - .../middleware/security.middleware.ts | 92 - src/security/security.controller.ts | 250 - src/security/security.module.ts | 61 - .../services/adaptive-rate-limiter.service.ts | 321 - src/security/services/api-quota.service.ts | 380 - .../services/cors-validation.service.ts | 337 - src/security/services/csp-utility.service.ts | 268 - .../services/ddos-protection.service.ts | 301 - .../services/file-validation.service.ts | 332 - .../services/input-sanitization.service.ts | 103 - src/security/services/ip-blocking.service.ts | 256 - .../services/malware-scanner.service.ts | 278 - .../services/rate-limiting.service.ts | 434 - .../services/security-headers.service.ts | 327 - .../services/user-tier-management.service.ts | 247 - .../validators/secure-file.validator.ts | 107 - src/services/AnalyticsService.ts | 107 - src/services/CacheOptimizationService.ts | 85 - src/services/DatabaseOptimizationService.ts | 386 - src/services/DocumentationService.ts | 492 - src/services/EnterpriseAuthService.ts | 609 - src/services/GatewayService.ts | 145 - src/services/GraphQLPerformanceService.ts | 56 - src/services/SecurityService.ts | 499 - src/services/StorageService.ts | 556 - src/services/TestingService.ts | 679 - src/static-cache/README.md | 473 - src/static-cache/cache-analytics.service.ts | 716 - .../cache-invalidation.service.ts | 460 - .../cache-management.controller.ts | 518 - src/static-cache/cache-warming.service.ts | 726 - .../middleware/static-cache.middleware.ts | 500 - .../models/static-cache.entity.ts | 193 - src/static-cache/static-cache.module.ts | 31 - .../static-content-cache.service.ts | 657 - src/storage/DataCompressor.ts | 507 - src/storage/MultiCloudManager.ts | 584 - src/storage/README.md | 402 - src/storage/StorageOptimizer.ts | 523 - src/storage/storage.controller.ts | 333 - src/storage/storage.module.ts | 29 - src/test/database.spec.ts | 52 - src/test/pagination.spec.ts | 96 - src/test/payload.spec.ts | 54 - src/test/rate-limiting-enhancement.spec.ts | 182 - src/testing/ContractTester.ts | 689 - src/testing/PerformanceBenchmark.ts | 623 - src/testing/TestGenerator.ts | 563 - src/testing/testing.controller.ts | 268 - src/testing/testing.module.ts | 31 - .../dto/create-transaction.dto.ts | 96 - src/transactions/dto/transaction-query.dto.ts | 47 - .../dto/update-transaction.dto.ts | 12 - .../enums/transaction-status.enum.ts | 13 - .../enums/transaction-type.enum.ts | 6 - src/transactions/transactions.controller.ts | 71 - src/transactions/transactions.module.ts | 4 - src/transactions/transactions.service.ts | 175 - src/types/api.types.ts | 242 - src/types/guards.ts | 257 - src/types/index.ts | 58 - src/types/prisma.types.ts | 213 - src/types/security.types.ts | 189 - src/types/service.types.ts | 136 - src/types/validation.types.ts | 133 - src/users/dto/create-user.dto.ts | 130 - src/users/dto/index.ts | 3 - src/users/dto/update-user.dto.ts | 4 - src/users/dto/user-response.dto.ts | 270 - src/users/dto/user.dto.ts | 41 + src/users/user.controller.ts | 166 - src/users/user.service.ts | 825 - src/users/users.controller.ts | 33 + src/users/users.module.ts | 27 +- src/users/users.service.ts | 86 + src/utils/type-validation.utils.ts | 409 - .../dto/batch-valuation-request.dto.ts | 35 - src/valuation/dto/property-features.dto.ts | 73 - src/valuation/valuation.controller.ts | 88 - src/valuation/valuation.module.ts | 14 - src/valuation/valuation.service.ts | 762 - src/valuation/valuation.types.ts | 74 - src/withdrawals/dto/create-withdrawal.dto.ts | 17 - src/withdrawals/dto/get-withdrawals.dto.ts | 26 - .../dto/update-withdrawal-status.dto.ts | 14 - src/withdrawals/withdrawals.controller.ts | 98 - src/withdrawals/withdrawals.module.ts | 14 - src/withdrawals/withdrawals.service.ts | 356 - test-suites/propchain-api-tests.json | 136 - test/analytics/analytics.service.spec.ts | 45 - test/api-keys/api-key.e2e-spec.ts | 226 - test/api-keys/api-key.service.spec.ts | 507 - test/api-keys/api-keys.e2e-spec.ts | 243 - test/auth/auth.e2e-spec.ts | 41 - test/auth/auth.service.spec.ts | 203 - .../common/errors/custom.exceptions.spec.ts | 5 - .../common/errors/error-responses.e2e-spec.ts | 0 test/auth/common/errors/error.filter.spec.ts | 5 - test/auth/mfa.service.spec.ts | 151 - test/auth/security.e2e-spec.ts | 210 - ...sensitive-endpoints-rate-limit.e2e-spec.ts | 318 - .../boundary-validation.service.spec.ts | 49 - .../common/cache-invalidation.service.spec.ts | 643 - test/common/cache-warming.service.spec.ts | 534 - test/common/errors/error_consistency.spec.ts | 57 - test/common/multi-level-cache.service.spec.ts | 444 - test/common/password-rotation.service.spec.ts | 538 - .../background-job-monitoring.service.spec.ts | 72 - test/communication/email.queue.spec.ts | 151 - test/config/config-manager.spec.ts | 44 - test/config/environment-config.spec.ts | 29 - test/config/feature-flags.spec.ts | 28 - test/database/database.integration.spec.ts | 306 - test/database/performance.benchmark.ts | 343 - test/database/prisma.service.spec.ts | 79 - test/database/test-container.ts | 174 - test/database/transaction-manager.spec.ts | 286 - test/documents/document.controller.spec.ts | 70 - test/documents/document.service.spec.ts | 175 - test/e2e-setup.ts | 171 - .../critical-user-flows.e2e.spec.ts.disabled | 588 - test/errors/error-classifier.spec.ts | 24 - test/errors/incident-responder.spec.ts | 35 - test/errors/recovery-manager.spec.ts | 25 - test/gateway/circuit-breaker.spec.ts | 50 - test/gateway/gateway.service.spec.ts | 56 - test/gateway/load-balancer.spec.ts | 39 - test/gateway/service-registry.spec.ts | 35 - test/health/health.controller.spec.ts | 356 - test/integration-setup.ts | 122 - test/integration/errorHandler.test.ts | 108 - test/jest-e2e.json | 14 - test/jest-unit.json | 12 - test/migrations/migration-safety.spec.ts | 42 - test/pagination/api-keys.pagination.spec.ts | 229 - .../pagination.integration.spec.ts.disabled | 248 - .../pagination/pagination.performance.spec.ts | 190 - test/pagination/pagination.performance.ts | 211 - test/pagination/pagination.service.spec.ts | 224 - test/performance-setup.ts | 202 - test/properties/properties.controller.spec.ts | 297 - ...ies.service.comprehensive.spec.ts.disabled | 535 - ...rties.service.integration.spec.ts.disabled | 388 - test/properties/properties.service.spec.ts | 639 - test/security-setup.ts | 268 - test/security/cors-validation.service.spec.ts | 83 - test/security/file-validation.service.spec.ts | 165 - ...ensitive-endpoint-rate-limit.guard.spec.ts | 364 - .../header-validation.middleware.spec.ts | 314 - .../input-sanitization.service.spec.ts | 57 - test/security/ip-blocking.service.spec.ts | 159 - test/security/rate-limit.middleware.spec.ts | 144 - test/security/rate-limiting.service.spec.ts | 170 - .../security/security-headers.service.spec.ts | 43 - test/security/security.e2e-spec.ts | 74 - test/security/security.middleware.spec.ts | 98 - .../security-headers.service.spec.ts.disabled | 376 - test/setup.ts | 108 - test/unit/donations/donations.service.spec.ts | 153 - test/unit/errors.test.ts | 136 - test/unit/logger.test.ts | 112 - .../withdrawals/withdrawals.service.spec.ts | 92 - test/users/user.service.spec.ts | 124 - test/validation/api-key-dto.spec.ts | 138 - test/validation/auth-dto.spec.ts | 213 - test/validation/auth-validation.e2e-spec.ts | 233 - test/validation/common-dto.spec.ts | 115 - test/validation/custom-validators.spec.ts | 136 - test/validation/document-dto.spec.ts | 194 - .../document-validation.e2e-spec.ts | 232 - test/validation/property-dto.spec.ts | 234 - .../property-validation.e2e-spec.ts | 268 - test/validation/user-dto.spec.ts | 131 - test/valuation/valuation.controller.spec.ts | 92 - test/valuation/valuation.service.spec.ts | 185 - test_out.txt | 119 - test_output.txt | Bin 7378 -> 0 bytes tsconfig.app.json | 7 +- tsconfig.ci.json | 18 - tsconfig.json | 12 +- tsconfig.spec.json | 23 - typedoc.json | 15 - update-reputation.dto.ts | 18 - validate-implementation.js | 137 - 710 files changed, 7085 insertions(+), 147118 deletions(-) delete mode 100644 .env.csp.example delete mode 100644 .env.development delete mode 100644 .env.production delete mode 100644 .env.staging delete mode 100644 .eslintrc.js delete mode 100644 .npmrc delete mode 100644 .prettierignore delete mode 100644 .prettierrc delete mode 100644 COMPRESSION_PR_DESCRIPTION.md delete mode 100644 Dockerfile delete mode 100644 GITHUB_PR_DESCRIPTION.md delete mode 100644 PR_DESCRIPTION.md create mode 100644 README.md delete mode 100644 TESTING_IMPLEMENTATION.md delete mode 100644 TYPE_SAFETY_PR.md delete mode 100644 admin.controller.ts delete mode 100644 admin.guard.ts delete mode 100644 admin.module.ts delete mode 100644 admin.service.ts delete mode 100644 benchmarks/chains/README.md delete mode 100644 benchmarks/chains/benchmark-reporter.ts delete mode 100644 benchmarks/chains/benchmark-runner.ts delete mode 100644 benchmarks/chains/index.ts delete mode 100644 benchmarks/chains/run-benchmarks.ts delete mode 100644 benchmarks/chains/stacks/auth.stack.ts delete mode 100644 benchmarks/chains/stacks/full.stack.ts delete mode 100644 benchmarks/chains/stacks/minimal.stack.ts delete mode 100644 benchmarks/chains/types/benchmark-types.ts delete mode 100644 benchmarks/chains/utils/performance-measurer.ts delete mode 100644 benchmarks/memory/README.md delete mode 100644 benchmarks/memory/heap-snapshot.ts delete mode 100644 benchmarks/memory/run-memory-profile.ts delete mode 100644 benchmarks/memory/scenarios.ts delete mode 100644 build_output.txt delete mode 100644 build_output_2.txt delete mode 100644 claims.e2e-spec.ts delete mode 100644 dashboard.dto.ts delete mode 100644 docker-compose.yml delete mode 100644 docs/API_SECURITY_GUIDE.md delete mode 100644 docs/API_VERSIONING.md delete mode 100644 docs/CSP_IMPLEMENTATION.md delete mode 100644 docs/DATABASE_OPTIMIZATION_GUIDE.md delete mode 100644 docs/DATABASE_SCHEMA.md delete mode 100644 docs/DEVELOPER_GUIDE.md delete mode 100644 docs/EMAIL_COMMUNICATION_GUIDE.md delete mode 100644 docs/ENVIRONMENT_VARIABLES.md delete mode 100644 docs/ERROR_HANDLING_GUIDE.md delete mode 100644 docs/LOAD_TESTING.md delete mode 100644 docs/MODULE_ORGANIZATION_GUIDE.md delete mode 100644 docs/PERFORMANCE.md delete mode 100644 docs/RATE_LIMITING_IMPLEMENTATION.md delete mode 100644 docs/SERVICE_LAYER_ARCHITECTURE.md delete mode 100644 docs/ZERO_DOWNTIME_MIGRATIONS.md delete mode 100644 docs/enhanced-rate-limiting.md delete mode 100644 docs/health-checks.md delete mode 100644 docs/observability.md delete mode 100644 docs/properties-api.md delete mode 100644 docs/testing.md delete mode 100644 docs/valuation-api.md delete mode 100644 eslint.config.js delete mode 100644 indexer-monitor.service.ts delete mode 100644 junit.xml delete mode 100644 loadtests/propchain-loadtest.js delete mode 100644 monitoring.module.ts delete mode 100644 pw_test_out.txt delete mode 100644 reputation.module.ts delete mode 100644 reputation.service.ts delete mode 100644 scripts/backup.sh delete mode 100644 scripts/init-db.sql delete mode 100755 scripts/loadtest-ci.sh delete mode 100644 scripts/restore.sh delete mode 100644 scripts/rollback-migration.js delete mode 100644 scripts/run-comprehensive-tests.ts delete mode 100644 scripts/test-restore.sh delete mode 100644 scripts/validate-migrations.js delete mode 100644 src/analytics/EventAggregator.ts delete mode 100644 src/analytics/MetricsCalculator.ts delete mode 100644 src/analytics/StreamProcessor.ts delete mode 100644 src/analytics/analytics.module.ts delete mode 100644 src/api-keys/README.md delete mode 100644 src/api-keys/SETUP.md delete mode 100644 src/api-keys/api-key-analytics.service.ts delete mode 100644 src/api-keys/api-key-rotation.scheduler.ts delete mode 100644 src/api-keys/api-key.controller.ts delete mode 100644 src/api-keys/api-key.module.ts delete mode 100644 src/api-keys/api-key.service.ts delete mode 100644 src/api-keys/api-key.types.ts delete mode 100644 src/api-keys/api-keys.module.ts delete mode 100644 src/api-keys/dto/api-key-query.dto.ts delete mode 100644 src/api-keys/dto/api-key-response.dto.ts delete mode 100644 src/api-keys/dto/create-api-key.dto.ts delete mode 100644 src/api-keys/dto/index.ts delete mode 100644 src/api-keys/dto/update-api-key.dto.ts delete mode 100644 src/api-keys/enums/api-key-scope.enum.ts delete mode 100644 src/api-keys/examples/properties-with-api-keys.example.ts delete mode 100644 src/app.ci.module.ts create mode 100644 src/app.controller.ts delete mode 100644 src/audit/AuditLogger.ts delete mode 100644 src/audit/ComplianceManager.ts delete mode 100644 src/audit/ForensicAnalyzer.ts delete mode 100644 src/audit/audit.controller.ts delete mode 100644 src/audit/audit.module.ts delete mode 100644 src/audit/audit.service.ts delete mode 100644 src/audit/entities/audit-log.entity.ts delete mode 100644 src/audit/interceptors/audit.interceptor.ts delete mode 100644 src/auth/OAuth2Provider.ts delete mode 100644 src/auth/SAMLProvider.ts delete mode 100644 src/auth/SocialAuth.ts delete mode 100644 src/auth/auth.controller.ts delete mode 100644 src/auth/auth.module.ts delete mode 100644 src/auth/auth.service.ts delete mode 100644 src/auth/auth.types.ts delete mode 100644 src/auth/constants.ts delete mode 100644 src/auth/decorators/roles.decorator.ts delete mode 100644 src/auth/dto/auth-response.dto.ts delete mode 100644 src/auth/dto/forgot-password.dto.ts delete mode 100644 src/auth/dto/index.ts delete mode 100644 src/auth/dto/login.dto.ts delete mode 100644 src/auth/dto/refresh-token.dto.ts delete mode 100644 src/auth/dto/reset-password.dto.ts delete mode 100644 src/auth/dto/verify-email-params.dto.ts delete mode 100644 src/auth/guards/jwt-auth.guard.ts delete mode 100644 src/auth/guards/local-auth.guard.ts delete mode 100644 src/auth/guards/login-attempts.guard.ts delete mode 100644 src/auth/guards/rbac.guard.ts delete mode 100644 src/auth/guards/throttle-auth.guard.ts delete mode 100644 src/auth/guards/wallet-signature.guard.ts delete mode 100644 src/auth/interceptors/security.interceptor.ts delete mode 100644 src/auth/mfa/index.ts delete mode 100644 src/auth/mfa/mfa.controller.ts delete mode 100644 src/auth/mfa/mfa.module.ts delete mode 100644 src/auth/mfa/mfa.service.ts delete mode 100644 src/auth/middleware/auth.middleware.ts delete mode 100644 src/auth/strategies/jwt.strategy.ts delete mode 100644 src/auth/strategies/local.strategy.ts delete mode 100644 src/auth/strategies/web3.strategy.ts delete mode 100644 src/auth/wallet-signature.service.ts delete mode 100644 src/backup-recovery/DISASTER_RECOVERY_RUNBOOK.md delete mode 100644 src/backup-recovery/README.md delete mode 100644 src/backup-recovery/SETUP_GUIDE.md delete mode 100644 src/backup-recovery/backup-cli.ts delete mode 100644 src/backup-recovery/backup-monitoring.service.ts delete mode 100644 src/backup-recovery/backup-recovery.controller.ts delete mode 100644 src/backup-recovery/backup-recovery.module.ts delete mode 100644 src/backup-recovery/backup-verification.service.ts delete mode 100644 src/backup-recovery/backup.types.ts delete mode 100644 src/backup-recovery/database-backup.service.ts delete mode 100644 src/backup-recovery/disaster-recovery.service.ts delete mode 100644 src/backup-recovery/document-backup.service.ts delete mode 100644 src/blockchain/blockchain.module.ts delete mode 100644 src/blockchain/blockchain.service.ts delete mode 100644 src/blockchain/controllers/external-ledger-event.controller.ts delete mode 100644 src/blockchain/dto/external-ledger-event.dto.ts delete mode 100644 src/blockchain/enums/supported-chain.enum.ts delete mode 100644 src/blockchain/guards/external-ledger-event.guard.ts delete mode 100644 src/blockchain/providers/provider.factory.ts delete mode 100644 src/blockchain/providers/submit-puzzle.provider.ts delete mode 100644 src/blockchain/services/external-ledger-event.service.ts delete mode 100644 src/blockchain/stellar/stellar-optimization.service.ts delete mode 100644 src/blockchain/stellar/stellar-payout.controller.ts delete mode 100644 src/blockchain/stellar/stellar-payout.module.ts delete mode 100644 src/blockchain/stellar/stellar-payout.service.ts delete mode 100644 src/blockchain/submit-puzzle.provider.spec.ts delete mode 100644 src/blockchain/tests/external-ledger-event.spec.ts delete mode 100644 src/blockchain/tests/external-ledger-event.validator.spec.ts delete mode 100644 src/blockchain/validators/external-ledger-event.validator.ts delete mode 100644 src/blockchain/wallet/wallet.service.ts delete mode 100644 src/cache/CacheManager.ts delete mode 100644 src/cache/CacheWarmer.ts delete mode 100644 src/cache/RedisCluster.ts delete mode 100644 src/common/api-version/api-version.module.ts delete mode 100644 src/common/api-version/constants.ts delete mode 100644 src/common/api-version/exports.ts delete mode 100644 src/common/api-version/guards/api-version.guard.ts delete mode 100644 src/common/api-version/index.ts delete mode 100644 src/common/api-version/interceptors/api-version.interceptor.ts delete mode 100644 src/common/api-version/middleware/api-version.middleware.ts delete mode 100644 src/common/api-version/services/api-version.service.ts delete mode 100644 src/common/api-version/services/version-manager.service.ts delete mode 100644 src/common/audit/audit.module.ts delete mode 100644 src/common/cache/cache-invalidation.service.ts delete mode 100644 src/common/cache/cache-warming.service.ts delete mode 100644 src/common/cache/cache.module.ts delete mode 100644 src/common/cache/multi-level-cache.service.ts delete mode 100644 src/common/compliance/compliance.module.ts delete mode 100644 src/common/controllers/audit.controller.ts delete mode 100644 src/common/controllers/compliance.controller.ts delete mode 100644 src/common/controllers/compression.controller.ts delete mode 100644 src/common/decorators/api-key-scopes.decorator.ts delete mode 100644 src/common/decorators/api-key.decorator.ts delete mode 100644 src/common/decorators/duplicate-protection.decorator.ts delete mode 100644 src/common/decorators/require-scopes.decorator.ts delete mode 100644 src/common/dto/compliance.dto.ts delete mode 100644 src/common/dto/date-range.dto.ts delete mode 100644 src/common/dto/index.ts delete mode 100644 src/common/dto/pagination.dto.ts delete mode 100644 src/common/dto/sort.dto.ts delete mode 100644 src/common/dtos/api-response.dto.ts delete mode 100644 src/common/errors/api-standard-error-response.decorator.ts delete mode 100644 src/common/errors/custom.exceptions.ts delete mode 100644 src/common/errors/error-formatter.service.ts delete mode 100644 src/common/errors/error-handling.module.ts delete mode 100644 src/common/errors/error.codes.ts delete mode 100644 src/common/errors/error.dto.ts delete mode 100644 src/common/errors/error.filter.spec.ts delete mode 100644 src/common/errors/error.filter.ts delete mode 100644 src/common/errors/error.types.ts delete mode 100644 src/common/errors/exceptions.ts delete mode 100644 src/common/errors/index.ts delete mode 100644 src/common/errors/timeout.exceptions.ts delete mode 100644 src/common/filters/all-exceptions.filter.ts delete mode 100644 src/common/filters/global-exception.filter.ts delete mode 100644 src/common/filters/validation-exception.filter.ts delete mode 100644 src/common/guards/api-key.guard.ts delete mode 100644 src/common/guards/duplicate-protection.guard.ts delete mode 100644 src/common/guards/idempotency.guard.ts delete mode 100644 src/common/interceptors/audit.interceptor.ts delete mode 100644 src/common/interceptors/response.interceptor.ts delete mode 100644 src/common/logger/correlation-id.ts delete mode 100644 src/common/logger/logger.module.ts delete mode 100644 src/common/logger/logger.service.ts delete mode 100644 src/common/logger/logging.interceptor.ts delete mode 100644 src/common/logger/logging.middleware.ts delete mode 100644 src/common/logging/correlation-id.ts delete mode 100644 src/common/logging/distributed-tracer.service.ts delete mode 100644 src/common/logging/logger.service.ts delete mode 100644 src/common/logging/logging.config.ts delete mode 100644 src/common/logging/logging.interceptor.ts delete mode 100644 src/common/logging/logging.middleware.ts delete mode 100644 src/common/logging/logging.module.ts delete mode 100644 src/common/middleware/payload-limit.middleware.ts delete mode 100644 src/common/middleware/payload-validation.middleware.ts delete mode 100644 src/common/middleware/request-size-limiter.middleware.ts delete mode 100644 src/common/modules/compression.module.ts delete mode 100644 src/common/pagination/PAGINATION.md delete mode 100644 src/common/pagination/PAGINATION_GUIDE.md delete mode 100644 src/common/pagination/cursor-pagination.dto.ts delete mode 100644 src/common/pagination/index.ts delete mode 100644 src/common/pagination/pagination.dto.ts delete mode 100644 src/common/pagination/pagination.module.ts delete mode 100644 src/common/pagination/pagination.service.ts delete mode 100644 src/common/pagination/tests/pagination.integration.spec.ts delete mode 100644 src/common/pagination/tests/pagination.performance.spec.ts delete mode 100644 src/common/pagination/tests/pagination.service.spec.ts delete mode 100644 src/common/patterns/dependency.injection.ts delete mode 100644 src/common/patterns/import.export.patterns.ts delete mode 100644 src/common/patterns/index.ts delete mode 100644 src/common/patterns/module.organization.service.ts delete mode 100644 src/common/patterns/module.structure.ts delete mode 100644 src/common/services/audit.service.ts delete mode 100644 src/common/services/base.service.ts delete mode 100644 src/common/services/cache.service.ts delete mode 100644 src/common/services/compliance-reporting.service.ts delete mode 100644 src/common/services/data-residency.service.ts delete mode 100644 src/common/services/data-retention.service.ts delete mode 100644 src/common/services/encryption.service.ts delete mode 100644 src/common/services/gdpr.service.ts delete mode 100644 src/common/services/idempotency.service.ts delete mode 100644 src/common/services/kyc-aml.service.ts delete mode 100644 src/common/services/password-rotation.service.ts delete mode 100644 src/common/services/redis.config.ts delete mode 100644 src/common/services/redis.constant.ts delete mode 100644 src/common/services/redis.module.ts delete mode 100644 src/common/services/redis.service.ts delete mode 100644 src/common/tests/compression.spec.ts delete mode 100644 src/common/tests/duplicate-protection.guard.spec.ts delete mode 100644 src/common/tests/duplicate.validator.spec.ts delete mode 100644 src/common/tests/idempotency.service.spec.ts delete mode 100644 src/common/utils/resilence.util.ts delete mode 100644 src/common/utils/timeout.util.ts delete mode 100644 src/common/validation/boundary-validation.module.ts delete mode 100644 src/common/validation/boundary-validation.service.ts delete mode 100644 src/common/validation/index.ts delete mode 100644 src/common/validators/duplicate.validator.ts delete mode 100644 src/common/validators/file-upload.validator.ts delete mode 100644 src/common/validators/index.ts delete mode 100644 src/common/validators/is-ethereum-address.validator.ts delete mode 100644 src/common/validators/is-strong-password.validator.ts delete mode 100644 src/common/validators/password.validator.ts delete mode 100644 src/common/validators/sql-injection.validator.ts delete mode 100644 src/common/validators/validation.utils.ts delete mode 100644 src/common/validators/xss.validator.ts delete mode 100644 src/common/validators/year-not-future.validator.ts delete mode 100644 src/communication/automation/workflow.service.ts delete mode 100644 src/communication/communication.module.ts delete mode 100644 src/communication/decorators/idempotent.decorator.ts delete mode 100644 src/communication/deliverability/deliverability.service.ts delete mode 100644 src/communication/email/email.analytics.ts delete mode 100644 src/communication/email/email.delivery-tracking.ts delete mode 100644 src/communication/email/email.queue.ts delete mode 100644 src/communication/email/email.service.ts delete mode 100644 src/communication/email/email.template.ts delete mode 100644 src/communication/index.ts delete mode 100644 src/communication/interceptors/idempotency.interceptor.ts delete mode 100644 src/communication/jobs/background-job-monitoring.service.ts delete mode 100644 src/communication/jobs/background-jobs.controller.ts delete mode 100644 src/communication/jobs/email-queue.processor.ts delete mode 100644 src/communication/multichannel/multichannel.service.ts delete mode 100644 src/communication/preferences/preference.service.ts delete mode 100644 src/communication/tests/background-job-monitoring.service.spec.ts delete mode 100644 src/config/ConfigManager.ts delete mode 100644 src/config/EnvironmentConfig.ts delete mode 100644 src/config/FeatureFlags.ts delete mode 100644 src/config/config.loader.ts delete mode 100644 src/config/configuration.controller.ts delete mode 100644 src/config/configuration.management.controller.ts delete mode 100644 src/config/configuration.module.ts delete mode 100644 src/config/configuration.service.ts delete mode 100644 src/config/configuration.ts delete mode 100644 src/config/interfaces/joi-schema-config.interface.ts delete mode 100644 src/config/observability.config.ts delete mode 100644 src/config/startup.validation.service.ts delete mode 100644 src/config/storage-multicloud.config.ts delete mode 100644 src/config/storage.config.ts delete mode 100644 src/config/utils/config.audit.ts delete mode 100644 src/config/utils/config.encryption.ts delete mode 100644 src/config/utils/config.hot-reload.ts delete mode 100644 src/config/utils/config.versioning.ts delete mode 100644 src/config/utils/cors-origin.validator.ts delete mode 100644 src/config/utils/env.sanitizer.ts delete mode 100644 src/config/utils/env.testing.ts delete mode 100644 src/config/utils/env.validator.ts delete mode 100644 src/config/validation/config.validation.ts delete mode 100644 src/config/valuation.config.ts delete mode 100644 src/database/ConnectionPool.ts delete mode 100644 src/database/QueryRouter.ts delete mode 100644 src/database/ReplicaManager.ts delete mode 100644 src/database/connection-health.service.ts delete mode 100644 src/database/database.module.ts delete mode 100644 src/database/index.ts delete mode 100644 src/database/optimization/connection.pool.ts delete mode 100644 src/database/optimization/database-optimization.controller.ts delete mode 100644 src/database/optimization/index-monitor.service.ts delete mode 100644 src/database/optimization/index.strategy.ts delete mode 100644 src/database/optimization/index.ts delete mode 100644 src/database/optimization/performance.monitor.ts delete mode 100644 src/database/optimization/query.optimizer.ts create mode 100644 src/database/prisma.module.ts create mode 100644 src/database/prisma.service.ts delete mode 100644 src/database/prisma/prisma.module.ts delete mode 100644 src/database/prisma/prisma.service.ts delete mode 100644 src/database/prisma/prisma.types.ts delete mode 100644 src/database/prisma/transaction-manager.service.ts delete mode 100644 src/database/retry-connection.ts delete mode 100644 src/docs/DocumentationGenerator.ts delete mode 100644 src/docs/ExampleGenerator.ts delete mode 100644 src/docs/InteractiveTester.ts delete mode 100644 src/documents/document.controller.ts delete mode 100644 src/documents/document.model.ts delete mode 100644 src/documents/document.service.ts delete mode 100644 src/documents/documents.module.ts delete mode 100644 src/documents/dto/document-query.dto.ts delete mode 100644 src/documents/dto/document-response.dto.ts delete mode 100644 src/documents/dto/download-query.dto.ts delete mode 100644 src/documents/dto/index.ts delete mode 100644 src/documents/dto/update-metadata.dto.ts delete mode 100644 src/documents/dto/upload-document.dto.ts delete mode 100644 src/documents/interceptors/document-upload.interceptor.ts delete mode 100644 src/documents/storage/file-storage.service.ts delete mode 100644 src/donations/donations.controller.ts delete mode 100644 src/donations/donations.module.ts delete mode 100644 src/donations/donations.service.ts delete mode 100644 src/donations/dto/donation-webhook.dto.ts delete mode 100644 src/errors/ErrorClassifier.ts delete mode 100644 src/errors/IncidentResponder.ts delete mode 100644 src/errors/RecoveryManager.ts delete mode 100644 src/errors/errors.module.ts delete mode 100644 src/examples/tiered-rate-limit-usage.controller.ts delete mode 100644 src/export/README.md delete mode 100644 src/export/dto/export.dto.ts delete mode 100644 src/export/export.controller.spec.ts delete mode 100644 src/export/export.controller.ts delete mode 100644 src/export/export.module.ts delete mode 100644 src/export/export.processor.ts delete mode 100644 src/export/export.service.ts delete mode 100644 src/feature-flags/README.md delete mode 100644 src/feature-flags/dto/feature-flag.dto.ts delete mode 100644 src/feature-flags/feature-flag-analytics.service.ts delete mode 100644 src/feature-flags/feature-flag-helper.service.ts delete mode 100644 src/feature-flags/feature-flag.controller.ts delete mode 100644 src/feature-flags/feature-flag.module.ts delete mode 100644 src/feature-flags/feature-flag.service.ts delete mode 100644 src/feature-flags/middleware/feature-flag.middleware.ts delete mode 100644 src/feature-flags/models/feature-flag.entity.ts delete mode 100644 src/files/files.controller.ts delete mode 100644 src/files/files.module.ts delete mode 100644 src/gateway/CircuitBreaker.ts delete mode 100644 src/gateway/LoadBalancer.ts delete mode 100644 src/gateway/ServiceRegistry.ts delete mode 100644 src/gateway/gateway.controller.ts delete mode 100644 src/gateway/gateway.module.ts delete mode 100644 src/graphql/PersistedQueries.ts delete mode 100644 src/graphql/QueryOptimizer.ts delete mode 100644 src/graphql/ResponseCache.ts delete mode 100644 src/health/health-analytics.service.ts delete mode 100644 src/health/health-scheduler.service.ts delete mode 100644 src/health/health.controller.ts delete mode 100644 src/health/health.module.ts delete mode 100644 src/health/indicators/blockchain.health.ts delete mode 100644 src/health/indicators/cpu.health.ts delete mode 100644 src/health/indicators/database.health.ts delete mode 100644 src/health/indicators/dependencies.health.ts delete mode 100644 src/health/indicators/disk.health.ts delete mode 100644 src/health/indicators/memory.health.ts delete mode 100644 src/health/indicators/redis.health.ts delete mode 100644 src/i18n/en/errors.json delete mode 100644 src/i18n/es/errors.json delete mode 100644 src/jobs/FailureHandler.ts delete mode 100644 src/jobs/JobManager.ts delete mode 100644 src/jobs/QueueProcessor.ts delete mode 100644 src/jobs/property-cleanup.service.ts delete mode 100644 src/libs/errors.ts delete mode 100644 src/libs/logger.ts delete mode 100644 src/main.ci.ts delete mode 100644 src/middleware/advanced/ARCHITECTURE.md delete mode 100644 src/middleware/advanced/CHECKLIST.md delete mode 100644 src/middleware/advanced/IMPLEMENTATION_SUMMARY.md delete mode 100644 src/middleware/advanced/QUICKSTART.md delete mode 100644 src/middleware/advanced/README.md delete mode 100644 src/middleware/advanced/circuit-breaker.middleware.spec.ts delete mode 100644 src/middleware/advanced/circuit-breaker.middleware.ts delete mode 100644 src/middleware/advanced/index.ts delete mode 100644 src/middleware/advanced/timeout.middleware.spec.ts delete mode 100644 src/middleware/advanced/timeout.middleware.ts delete mode 100644 src/middleware/advanced/usage-examples.ts delete mode 100644 src/middleware/compression.middleware.ts delete mode 100644 src/middleware/errorHandler.ts delete mode 100644 src/models/AuditLog.ts delete mode 100644 src/models/Configuration.ts delete mode 100644 src/models/ErrorReport.ts delete mode 100644 src/models/Job.ts delete mode 100644 src/models/Notification.ts delete mode 100644 src/models/api-key.entity.ts delete mode 100644 src/models/document.entity.ts delete mode 100644 src/models/donation.entity.ts delete mode 100644 src/models/index.ts delete mode 100644 src/models/permission.entity.ts delete mode 100644 src/models/property.entity.ts delete mode 100644 src/models/role.entity.ts delete mode 100644 src/models/transaction.entity.ts delete mode 100644 src/models/user.entity.ts delete mode 100644 src/models/withdrawal.entity.ts delete mode 100644 src/monitoring/indexer-monitor.controller.ts delete mode 100644 src/monitoring/tests/indexer-monitor.controller.spec.ts delete mode 100644 src/monitoring/tests/indexer-monitor.service.spec.ts delete mode 100644 src/notifications/ChannelManager.ts delete mode 100644 src/notifications/NotificationManager.ts delete mode 100644 src/notifications/TemplateEngine.ts delete mode 100644 src/observability/metrics.interceptor.ts delete mode 100644 src/observability/observability.controller.ts delete mode 100644 src/observability/observability.module.ts delete mode 100644 src/observability/pagination.metrics.ts delete mode 100644 src/observability/payload.metrics.ts delete mode 100644 src/observability/performance-monitor.service.ts delete mode 100644 src/observability/tracing.service.ts delete mode 100644 src/properties/dto/create-property.dto.ts delete mode 100644 src/properties/dto/index.ts delete mode 100644 src/properties/dto/property-extra.dto.ts delete mode 100644 src/properties/dto/property-query.dto.ts delete mode 100644 src/properties/dto/property-response.dto.ts delete mode 100644 src/properties/dto/property-search.dto.ts create mode 100644 src/properties/dto/property.dto.ts delete mode 100644 src/properties/dto/update-property.dto.ts delete mode 100644 src/properties/entities/property.entity.ts delete mode 100644 src/properties/properties-admin.controller.ts delete mode 100644 src/properties/search/property-search.service.ts delete mode 100644 src/properties/search/search-analytics.service.ts delete mode 100644 src/puzzles/puzzles.controller.ts delete mode 100644 src/puzzles/puzzles.repository.ts delete mode 100644 src/puzzles/puzzles.service.ts delete mode 100644 src/rbac/dto/assign-permissions.dto.ts delete mode 100644 src/rbac/dto/assign-role.dto.ts delete mode 100644 src/rbac/dto/create-permission.dto.ts delete mode 100644 src/rbac/dto/create-role.dto.ts delete mode 100644 src/rbac/dto/index.ts delete mode 100644 src/rbac/dto/update-role.dto.ts delete mode 100644 src/rbac/enums/action.enum.ts delete mode 100644 src/rbac/enums/index.ts delete mode 100644 src/rbac/enums/predefined-role.enum.ts delete mode 100644 src/rbac/enums/resource.enum.ts delete mode 100644 src/rbac/rbac.module.ts delete mode 100644 src/rbac/rbac.service.ts delete mode 100644 src/search/dto/search.dto.ts delete mode 100644 src/search/entities/search-analytics.entity.ts delete mode 100644 src/search/entities/search-cache.entity.ts delete mode 100644 src/search/search.controller.spec.ts delete mode 100644 src/search/search.controller.ts delete mode 100644 src/search/search.module.ts delete mode 100644 src/search/search.service.ts delete mode 100644 src/security/CSPManager.ts delete mode 100644 src/security/SecurityHeaders.ts delete mode 100644 src/security/SecurityScanner.ts delete mode 100644 src/security/api/abuse.detection.ts delete mode 100644 src/security/api/auth.hardening.ts delete mode 100644 src/security/api/index.ts delete mode 100644 src/security/api/request.validation.ts delete mode 100644 src/security/api/security.headers.ts delete mode 100644 src/security/api/security.testing.ts delete mode 100644 src/security/api/threat.detection.ts delete mode 100644 src/security/config/csp.config.ts delete mode 100644 src/security/config/multer.config.ts delete mode 100644 src/security/controllers/csp-violation.controller.ts delete mode 100644 src/security/controllers/rate-limit-analytics.controller.ts delete mode 100644 src/security/controllers/user-tier-management.controller.ts delete mode 100644 src/security/csp.module.ts delete mode 100644 src/security/decorators/rate-limit.decorator.ts delete mode 100644 src/security/decorators/sensitive-rate-limit.decorator.ts delete mode 100644 src/security/decorators/tiered-rate-limit.decorator.ts delete mode 100644 src/security/guards/advanced-rate-limit.guard.ts delete mode 100644 src/security/guards/sensitive-endpoint-rate-limit.guard.ts delete mode 100644 src/security/middleware/csp.middleware.ts delete mode 100644 src/security/middleware/header-validation.middleware.ts delete mode 100644 src/security/middleware/rate-limit.middleware.ts delete mode 100644 src/security/middleware/security.middleware.ts delete mode 100644 src/security/security.controller.ts delete mode 100644 src/security/security.module.ts delete mode 100644 src/security/services/adaptive-rate-limiter.service.ts delete mode 100644 src/security/services/api-quota.service.ts delete mode 100644 src/security/services/cors-validation.service.ts delete mode 100644 src/security/services/csp-utility.service.ts delete mode 100644 src/security/services/ddos-protection.service.ts delete mode 100644 src/security/services/file-validation.service.ts delete mode 100644 src/security/services/input-sanitization.service.ts delete mode 100644 src/security/services/ip-blocking.service.ts delete mode 100644 src/security/services/malware-scanner.service.ts delete mode 100644 src/security/services/rate-limiting.service.ts delete mode 100644 src/security/services/security-headers.service.ts delete mode 100644 src/security/services/user-tier-management.service.ts delete mode 100644 src/security/validators/secure-file.validator.ts delete mode 100644 src/services/AnalyticsService.ts delete mode 100644 src/services/CacheOptimizationService.ts delete mode 100644 src/services/DatabaseOptimizationService.ts delete mode 100644 src/services/DocumentationService.ts delete mode 100644 src/services/EnterpriseAuthService.ts delete mode 100644 src/services/GatewayService.ts delete mode 100644 src/services/GraphQLPerformanceService.ts delete mode 100644 src/services/SecurityService.ts delete mode 100644 src/services/StorageService.ts delete mode 100644 src/services/TestingService.ts delete mode 100644 src/static-cache/README.md delete mode 100644 src/static-cache/cache-analytics.service.ts delete mode 100644 src/static-cache/cache-invalidation.service.ts delete mode 100644 src/static-cache/cache-management.controller.ts delete mode 100644 src/static-cache/cache-warming.service.ts delete mode 100644 src/static-cache/middleware/static-cache.middleware.ts delete mode 100644 src/static-cache/models/static-cache.entity.ts delete mode 100644 src/static-cache/static-cache.module.ts delete mode 100644 src/static-cache/static-content-cache.service.ts delete mode 100644 src/storage/DataCompressor.ts delete mode 100644 src/storage/MultiCloudManager.ts delete mode 100644 src/storage/README.md delete mode 100644 src/storage/StorageOptimizer.ts delete mode 100644 src/storage/storage.controller.ts delete mode 100644 src/storage/storage.module.ts delete mode 100644 src/test/database.spec.ts delete mode 100644 src/test/pagination.spec.ts delete mode 100644 src/test/payload.spec.ts delete mode 100644 src/test/rate-limiting-enhancement.spec.ts delete mode 100644 src/testing/ContractTester.ts delete mode 100644 src/testing/PerformanceBenchmark.ts delete mode 100644 src/testing/TestGenerator.ts delete mode 100644 src/testing/testing.controller.ts delete mode 100644 src/testing/testing.module.ts delete mode 100644 src/transactions/dto/create-transaction.dto.ts delete mode 100644 src/transactions/dto/transaction-query.dto.ts delete mode 100644 src/transactions/dto/update-transaction.dto.ts delete mode 100644 src/transactions/enums/transaction-status.enum.ts delete mode 100644 src/transactions/enums/transaction-type.enum.ts delete mode 100644 src/transactions/transactions.controller.ts delete mode 100644 src/transactions/transactions.module.ts delete mode 100644 src/transactions/transactions.service.ts delete mode 100644 src/types/api.types.ts delete mode 100644 src/types/guards.ts delete mode 100644 src/types/index.ts delete mode 100644 src/types/prisma.types.ts delete mode 100644 src/types/security.types.ts delete mode 100644 src/types/service.types.ts delete mode 100644 src/types/validation.types.ts delete mode 100644 src/users/dto/create-user.dto.ts delete mode 100644 src/users/dto/index.ts delete mode 100644 src/users/dto/update-user.dto.ts delete mode 100644 src/users/dto/user-response.dto.ts create mode 100644 src/users/dto/user.dto.ts delete mode 100644 src/users/user.controller.ts delete mode 100644 src/users/user.service.ts create mode 100644 src/users/users.controller.ts create mode 100644 src/users/users.service.ts delete mode 100644 src/utils/type-validation.utils.ts delete mode 100644 src/valuation/dto/batch-valuation-request.dto.ts delete mode 100644 src/valuation/dto/property-features.dto.ts delete mode 100644 src/valuation/valuation.controller.ts delete mode 100644 src/valuation/valuation.module.ts delete mode 100644 src/valuation/valuation.service.ts delete mode 100644 src/valuation/valuation.types.ts delete mode 100644 src/withdrawals/dto/create-withdrawal.dto.ts delete mode 100644 src/withdrawals/dto/get-withdrawals.dto.ts delete mode 100644 src/withdrawals/dto/update-withdrawal-status.dto.ts delete mode 100644 src/withdrawals/withdrawals.controller.ts delete mode 100644 src/withdrawals/withdrawals.module.ts delete mode 100644 src/withdrawals/withdrawals.service.ts delete mode 100644 test-suites/propchain-api-tests.json delete mode 100644 test/analytics/analytics.service.spec.ts delete mode 100644 test/api-keys/api-key.e2e-spec.ts delete mode 100644 test/api-keys/api-key.service.spec.ts delete mode 100644 test/api-keys/api-keys.e2e-spec.ts delete mode 100644 test/auth/auth.e2e-spec.ts delete mode 100644 test/auth/auth.service.spec.ts delete mode 100644 test/auth/common/errors/custom.exceptions.spec.ts delete mode 100644 test/auth/common/errors/error-responses.e2e-spec.ts delete mode 100644 test/auth/common/errors/error.filter.spec.ts delete mode 100644 test/auth/mfa.service.spec.ts delete mode 100644 test/auth/security.e2e-spec.ts delete mode 100644 test/auth/sensitive-endpoints-rate-limit.e2e-spec.ts delete mode 100644 test/common/boundary-validation.service.spec.ts delete mode 100644 test/common/cache-invalidation.service.spec.ts delete mode 100644 test/common/cache-warming.service.spec.ts delete mode 100644 test/common/errors/error_consistency.spec.ts delete mode 100644 test/common/multi-level-cache.service.spec.ts delete mode 100644 test/common/password-rotation.service.spec.ts delete mode 100644 test/communication/background-job-monitoring.service.spec.ts delete mode 100644 test/communication/email.queue.spec.ts delete mode 100644 test/config/config-manager.spec.ts delete mode 100644 test/config/environment-config.spec.ts delete mode 100644 test/config/feature-flags.spec.ts delete mode 100644 test/database/database.integration.spec.ts delete mode 100644 test/database/performance.benchmark.ts delete mode 100644 test/database/prisma.service.spec.ts delete mode 100644 test/database/test-container.ts delete mode 100644 test/database/transaction-manager.spec.ts delete mode 100644 test/documents/document.controller.spec.ts delete mode 100644 test/documents/document.service.spec.ts delete mode 100644 test/e2e-setup.ts delete mode 100644 test/e2e/critical-user-flows.e2e.spec.ts.disabled delete mode 100644 test/errors/error-classifier.spec.ts delete mode 100644 test/errors/incident-responder.spec.ts delete mode 100644 test/errors/recovery-manager.spec.ts delete mode 100644 test/gateway/circuit-breaker.spec.ts delete mode 100644 test/gateway/gateway.service.spec.ts delete mode 100644 test/gateway/load-balancer.spec.ts delete mode 100644 test/gateway/service-registry.spec.ts delete mode 100644 test/health/health.controller.spec.ts delete mode 100644 test/integration-setup.ts delete mode 100644 test/integration/errorHandler.test.ts delete mode 100644 test/jest-e2e.json delete mode 100644 test/jest-unit.json delete mode 100644 test/migrations/migration-safety.spec.ts delete mode 100644 test/pagination/api-keys.pagination.spec.ts delete mode 100644 test/pagination/pagination.integration.spec.ts.disabled delete mode 100644 test/pagination/pagination.performance.spec.ts delete mode 100644 test/pagination/pagination.performance.ts delete mode 100644 test/pagination/pagination.service.spec.ts delete mode 100644 test/performance-setup.ts delete mode 100644 test/properties/properties.controller.spec.ts delete mode 100644 test/properties/properties.service.comprehensive.spec.ts.disabled delete mode 100644 test/properties/properties.service.integration.spec.ts.disabled delete mode 100644 test/properties/properties.service.spec.ts delete mode 100644 test/security-setup.ts delete mode 100644 test/security/cors-validation.service.spec.ts delete mode 100644 test/security/file-validation.service.spec.ts delete mode 100644 test/security/guards/sensitive-endpoint-rate-limit.guard.spec.ts delete mode 100644 test/security/header-validation.middleware.spec.ts delete mode 100644 test/security/input-sanitization.service.spec.ts delete mode 100644 test/security/ip-blocking.service.spec.ts delete mode 100644 test/security/rate-limit.middleware.spec.ts delete mode 100644 test/security/rate-limiting.service.spec.ts delete mode 100644 test/security/security-headers.service.spec.ts delete mode 100644 test/security/security.e2e-spec.ts delete mode 100644 test/security/security.middleware.spec.ts delete mode 100644 test/security/services/security-headers.service.spec.ts.disabled delete mode 100644 test/setup.ts delete mode 100644 test/unit/donations/donations.service.spec.ts delete mode 100644 test/unit/errors.test.ts delete mode 100644 test/unit/logger.test.ts delete mode 100644 test/unit/withdrawals/withdrawals.service.spec.ts delete mode 100644 test/users/user.service.spec.ts delete mode 100644 test/validation/api-key-dto.spec.ts delete mode 100644 test/validation/auth-dto.spec.ts delete mode 100644 test/validation/auth-validation.e2e-spec.ts delete mode 100644 test/validation/common-dto.spec.ts delete mode 100644 test/validation/custom-validators.spec.ts delete mode 100644 test/validation/document-dto.spec.ts delete mode 100644 test/validation/document-validation.e2e-spec.ts delete mode 100644 test/validation/property-dto.spec.ts delete mode 100644 test/validation/property-validation.e2e-spec.ts delete mode 100644 test/validation/user-dto.spec.ts delete mode 100644 test/valuation/valuation.controller.spec.ts delete mode 100644 test/valuation/valuation.service.spec.ts delete mode 100644 test_out.txt delete mode 100644 test_output.txt delete mode 100644 tsconfig.ci.json delete mode 100644 tsconfig.spec.json delete mode 100644 typedoc.json delete mode 100644 update-reputation.dto.ts delete mode 100644 validate-implementation.js diff --git a/.env.csp.example b/.env.csp.example deleted file mode 100644 index 470b735c..00000000 --- a/.env.csp.example +++ /dev/null @@ -1,108 +0,0 @@ -# ============================================ -# Content Security Policy (CSP) Configuration -# ============================================ -# Configure trusted sources for different content types -# These domains will be allowed to load resources - -# -------------------------------------------- -# Script Sources (CDNs, Analytics, etc.) -# -------------------------------------------- -# Trusted JavaScript CDNs -CDN_SCRIPT_1=https://cdn.jsdelivr.net -CDN_SCRIPT_2=https://unpkg.com -# Add more as needed: -# CDN_SCRIPT_3=https://cdnjs.cloudflare.com - -# -------------------------------------------- -# Style Sources (CSS Frameworks, Fonts) -# -------------------------------------------- -# Trusted CSS CDNs -CDN_STYLE_1=https://fonts.googleapis.com -# Add more as needed: -# CDN_STYLE_2=https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap - -# -------------------------------------------- -# Image Sources -# -------------------------------------------- -# Trusted image CDNs and services -CDN_IMAGE_1=https://images.unsplash.com -CDN_IMAGE_2=https://cdn.example.com -# Add your image storage CDN: -# CDN_IMAGE_3=https://images.propchain.com - -# -------------------------------------------- -# Font Sources -# -------------------------------------------- -# Trusted font CDNs -CDN_FONT_1=https://fonts.gstatic.com -CDN_FONT_2=https://cdn.jsdelivr.net -# Add more as needed: -# CDN_FONT_3=https://use.typekit.net - -# -------------------------------------------- -# API Endpoints (connect-src) -# -------------------------------------------- -# Allowed API endpoints for fetch/XHR/WebSocket -BACKEND_URL=https://api.propchain.com -API_ENDPOINT_1=https://api.propchain.com -API_ENDPOINT_2=https://analytics.propchain.com -# Add WebSocket if needed: -# WS_ENDPOINT=wss://ws.propchain.com - -# -------------------------------------------- -# Third-Party Integrations -# -------------------------------------------- - -# Analytics Services -ANALYTICS_DOMAIN=https://www.google-analytics.com -# Add more analytics: -# ANALYTICS_DOMAIN_2=https://www.googletagmanager.com - -# Payment Gateways -STRIPE_DOMAIN=https://js.stripe.com -PAYPAL_DOMAIN=https://www.paypal.com -# Add more payment processors: -# SQUARE_DOMAIN=https://squareup.com - -# -------------------------------------------- -# Frame Ancestors (Clickjacking Protection) -# -------------------------------------------- -# By default, framing is blocked ('none') -# If you need to allow specific domains to embed your content: -# FRAME_ANCESTOR_1=https://trusted-partner.com -# FRAME_ANCESTOR_2=https://app.propchain.com - -# -------------------------------------------- -# CSP Mode Configuration -# -------------------------------------------- -# Set to 'true' to use report-only mode (testing) -# Set to 'false' to enforce policy (production) -CSP_REPORT_ONLY=false - -# Enable nonce-based inline scripts -# Set to 'true' for production, 'false' for easier debugging in dev -CSP_ENABLE_NONCE=true - -# -------------------------------------------- -# Environment-Specific Settings -# -------------------------------------------- -# NODE_ENV should be set appropriately: -# - development: Permissive policies, report-only mode -# - staging: Production-like with report-only -# - production: Strict enforcement - -# Example for different environments: -# Development (.env.development): -# NODE_ENV=development -# CSP_REPORT_ONLY=true -# CDN_SCRIPT_1=http://localhost:8080 - -# Staging (.env.staging): -# NODE_ENV=staging -# CSP_REPORT_ONLY=true -# BACKEND_URL=https://staging-api.propchain.com - -# Production (.env.production): -# NODE_ENV=production -# CSP_REPORT_ONLY=false -# BACKEND_URL=https://api.propchain.com diff --git a/.env.development b/.env.development deleted file mode 100644 index 566f457d..00000000 --- a/.env.development +++ /dev/null @@ -1,60 +0,0 @@ -# Development Environment Configuration -NODE_ENV=development -PORT=3000 -HOST=localhost - -# CORS - Allow localhost in development -CORS_ORIGIN=http://localhost:3000,http://localhost:5173,http://127.0.0.1:3000,http://127.0.0.1:5173 - -# Database -DATABASE_URL=postgresql://postgres:password@localhost:5432/propchain_dev - -# JWT -JWT_SECRET=dev-super-secret-jwt-key-32-chars-minimum -JWT_REFRESH_SECRET=dev-super-secret-refresh-key-32-chars -ENCRYPTION_KEY=dev-32-char-encryption-key-here - -# Blockchain -BLOCKCHAIN_NETWORK=sepolia -RPC_URL=https://sepolia.infura.io/v3/YOUR_PROJECT_ID -PRIVATE_KEY=0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef - -# Session -SESSION_SECRET=dev-session-secret-key-32-chars-min - -# Email -EMAIL_FROM=dev@propchain.local - -# Observability Configuration -OTEL_SERVICE_NAME=propchain-backend -OTEL_SERVICE_VERSION=1.0.0 -OTEL_ENABLED=true -OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 -OTEL_SAMPLING_RATE=1.0 - -# Metrics Configuration -METRICS_ENABLED=true -METRICS_PATH=/metrics -METRICS_PORT=9090 - -# Performance Monitoring -PERFORMANCE_MONITORING_ENABLED=true -PERFORMANCE_MONITORING_INTERVAL=30000 -PERFORMANCE_METRICS_RETENTION=86400000 - -# Alert Thresholds -CPU_ALERT_THRESHOLD=90 -MEMORY_ALERT_THRESHOLD=90 -ERROR_RATE_ALERT_THRESHOLD=5 -RESPONSE_TIME_ALERT_THRESHOLD=5000 - -# Compression Configuration -COMPRESSION_ENABLED=true -COMPRESSION_LEVEL=6 -COMPRESSION_THRESHOLD=1024 -COMPRESSION_CONTENT_TYPES=text/,application/json,application/javascript,application/xml,application/rss+xml,application/x-javascript,image/svg+xml,font/,application/wasm - -# Logging -LOG_LEVEL=info -LOG_FORMAT=json -LOGGING_ENABLED=true diff --git a/.env.example b/.env.example index 70ce8072..7250b80d 100644 --- a/.env.example +++ b/.env.example @@ -1,82 +1,8 @@ -# Application Configuration -NODE_ENV=development +# Environment Variables +DATABASE_URL=postgresql://user:password@localhost:5432/propchain PORT=3000 -HOST=0.0.0.0 -API_PREFIX=api -# CORS Configuration: -# - Development: Use specific localhost origins (e.g., http://localhost:3000,http://localhost:5173) -# - Production/Staging: Use specific production domains (e.g., https://propchain.io,https://app.propchain.io) -# - Wildcard '*' is only allowed in development/test environments -# - Multiple origins can be comma-separated: https://example.com,https://api.example.com -CORS_ORIGIN=http://localhost:3000,http://localhost:5173 -SWAGGER_ENABLED=true - -# Database Configuration -DATABASE_URL=postgresql://postgres:password@localhost:5432/propchain - -# Redis Configuration -REDIS_HOST=localhost -REDIS_PORT=6379 -REDIS_PASSWORD= -REDIS_DB=0 - -# Security Configuration -JWT_SECRET=your-super-secret-jwt-key-32-chars-minimum -JWT_EXPIRES_IN=1h -JWT_REFRESH_SECRET=your-super-secret-refresh-key-32-chars -JWT_REFRESH_EXPIRES_IN=7d -ENCRYPTION_KEY=your-32-char-encryption-key-here -SESSION_SECRET=your-session-secret-key-32-chars-minimum -BCRYPT_ROUNDS=12 - -# Blockchain/Web3 Configuration -BLOCKCHAIN_NETWORK=sepolia -RPC_URL=https://sepolia.infura.io/v3/YOUR_PROJECT_ID -PRIVATE_KEY=0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef -ETHERSCAN_API_KEY=your-etherscan-api-key -WEB3_STORAGE_TOKEN=your-web3-storage-token - -# IPFS Configuration -IPFS_GATEWAY_URL=https://ipfs.io/ipfs/ -IPFS_API_URL=https://ipfs.infura.io:5001 -IPFS_PROJECT_ID=your-ipfs-project-id -IPFS_PROJECT_SECRET=your-ipfs-project-secret - -# Email Configuration -SMTP_HOST=smtp.mailtrap.io -SMTP_PORT=587 -SMTP_USER=your-smtp-user -SMTP_PASS=your-smtp-pass -EMAIL_FROM=noreply@propchain.io - -# External Services Configuration -COINGECKO_API_KEY=your-coingecko-api-key -OPENSEA_API_KEY=your-opensea-api-key -ZILLOW_API_KEY=your-zillow-api-key - -# File Upload Security Configuration -MAX_FILE_SIZE=10485760 -MAX_FILES_PER_UPLOAD=10 -ALLOWED_FILE_TYPES=image/jpeg,image/png,image/gif,application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document -VALIDATE_MAGIC_NUMBERS=true -MALWARE_SCANNING_ENABLED=true -CLAMAV_HOST=localhost -CLAMAV_PORT=3310 -CLAMAV_TIMEOUT=30000 -MAX_SCAN_SIZE_BYTES=26214400 -REDFIN_API_KEY=your-redfin-api-key -CORE_LOGIC_API_KEY=your-core-logic-api-key -MAXMIND_LICENSE_KEY=your-maxmind-license-key - -# Storage Configuration -STORAGE_PROVIDER=memory -STORAGE_SIGNED_URL_EXPIRES_IN=900 -STORAGE_SIGNING_SECRET=local-storage-signing-secret +NODE_ENV=development -# S3 Configuration (if STORAGE_PROVIDER=s3) -S3_BUCKET=propchain-documents -S3_REGION=us-east-1 -S3_ACCESS_KEY_ID=your-s3-access-key-id -S3_SECRET_ACCESS_KEY=your-s3-secret-access-key -S3_ENDPOINT= -S3_FORCE_PATH_STYLE=false +# JWT Configuration +JWT_SECRET=your-super-secret-jwt-key-change-in-production +JWT_EXPIRES_IN=7d diff --git a/.env.production b/.env.production deleted file mode 100644 index dd9d8b69..00000000 --- a/.env.production +++ /dev/null @@ -1,28 +0,0 @@ -# Production Environment Configuration -NODE_ENV=production -PORT=3000 -HOST=0.0.0.0 - -# CORS - REQUIRED: Specify production domains (comma-separated) -# Example: CORS_ORIGIN=https://propchain.io,https://app.propchain.io -# WARNING: Wildcard '*' is NOT allowed in production -CORS_ORIGIN=https://your-production-domain.com - -# Database -DATABASE_URL=postgresql://user:secure_password@prod-db:5432/propchain_prod - -# JWT -JWT_SECRET=prod-super-secret-jwt-key-32-chars-minimum -JWT_REFRESH_SECRET=prod-super-secret-refresh-key-32-chars -ENCRYPTION_KEY=prod-32-char-encryption-key-here - -# Blockchain -BLOCKCHAIN_NETWORK=mainnet -RPC_URL=https://mainnet.infura.io/v3/YOUR_PROJECT_ID -PRIVATE_KEY=0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef - -# Session -SESSION_SECRET=prod-session-secret-key-32-chars-min - -# Email -EMAIL_FROM=noreply@propchain.io diff --git a/.env.staging b/.env.staging deleted file mode 100644 index 3b011e59..00000000 --- a/.env.staging +++ /dev/null @@ -1,28 +0,0 @@ -# Staging Environment Configuration -NODE_ENV=staging -PORT=3000 -HOST=0.0.0.0 - -# CORS - REQUIRED: Specify staging domains (comma-separated) -# Example: CORS_ORIGIN=https://staging.propchain.io,https://staging-app.propchain.io -# WARNING: Wildcard '*' is NOT allowed in staging -CORS_ORIGIN=https://your-staging-domain.com - -# Database -DATABASE_URL=postgresql://user:password@staging-db:5432/propchain_staging - -# JWT -JWT_SECRET=staging-super-secret-jwt-key-32-chars-minimum -JWT_REFRESH_SECRET=staging-super-secret-refresh-key-32-chars -ENCRYPTION_KEY=staging-32-char-encryption-key-here - -# Blockchain -BLOCKCHAIN_NETWORK=sepolia -RPC_URL=https://sepolia.infura.io/v3/YOUR_PROJECT_ID -PRIVATE_KEY=0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef - -# Session -SESSION_SECRET=staging-session-secret-key-32-chars-min - -# Email -EMAIL_FROM=staging@propchain.io diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 6f2efefc..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,58 +0,0 @@ -module.exports = { - parser: '@typescript-eslint/parser', - parserOptions: { - project: 'tsconfig.json', - tsconfigRootDir: __dirname, - sourceType: 'module', - }, - plugins: ['@typescript-eslint/eslint-plugin'], - extends: ['plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'], - root: true, - env: { - node: true, - jest: true, - }, - ignorePatterns: ['.eslintrc.js', 'dist/', 'node_modules/', 'coverage/', 'test/', '**/*.spec.ts', '**/*.e2e-spec.ts'], - rules: { - '@typescript-eslint/interface-name-prefix': 'off', - '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/explicit-module-boundary-types': 'off', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-unused-vars': 'off', - '@typescript-eslint/ban-ts-comment': 'warn', - '@typescript-eslint/no-non-null-assertion': 'warn', - '@typescript-eslint/no-var-requires': 'error', - 'prettier/prettier': 'error', - 'no-console': 'off', - 'no-debugger': 'error', - 'prefer-const': 'error', - 'no-var': 'error', - 'object-shorthand': 'error', - 'prefer-template': 'error', - 'prefer-arrow-callback': 'error', - 'arrow-spacing': 'error', - 'comma-dangle': ['error', 'always-multiline'], - semi: ['error', 'always'], - quotes: 'off', - indent: 'off', - '@typescript-eslint/indent': 'off', - 'max-len': 'off', - 'eol-last': 'error', - 'no-trailing-spaces': 'error', - 'padded-blocks': ['error', 'never'], - 'space-before-function-paren': [ - 'error', - { - anonymous: 'always', - named: 'never', - asyncArrow: 'always', - }, - ], - 'keyword-spacing': 'error', - 'space-infix-ops': 'error', - 'object-curly-spacing': ['error', 'always'], - 'array-bracket-spacing': ['error', 'never'], - 'brace-style': ['error', '1tbs'], - curly: 'error', - }, -}; diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1842314..dfbdbdcb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,112 +4,17 @@ on: push: branches: [main, develop] pull_request: - branches: [main, develop] - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true + branches: [main] env: NODE_ENV: test - PORT: "3000" - API_PREFIX: api - CORS_ORIGIN: http://localhost:3001 - DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/propchain_ci?sslmode=disable - TEST_DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/propchain_ci?sslmode=disable - E2E_DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/propchain_ci?sslmode=disable - REDIS_URL: redis://127.0.0.1:6379/0 - TEST_REDIS_URL: redis://127.0.0.1:6379/0 - E2E_REDIS_URL: redis://127.0.0.1:6379/0 - REDIS_HOST: 127.0.0.1 - REDIS_PORT: "6379" - REDIS_DB: "0" - JWT_SECRET: ciJwtSigningKeyAlphaNumericValue0001 - JWT_REFRESH_SECRET: ciRefreshSigningKeyAlphaNumeric0002 - ENCRYPTION_KEY: C1EncKeyAlphaNumericValue0000001 - SESSION_SECRET: ciSessionSigningKeyAlphaNumeric0003 - EMAIL_FROM: ci@propchain.local - RPC_URL: http://127.0.0.1:8545 - PRIVATE_KEY: 0x1111111111111111111111111111111111111111111111111111111111111111 - STORAGE_PROVIDER: memory - MOCK_BLOCKCHAIN: "true" + DATABASE_URL: postgresql://postgres:postgres@localhost:5432/propchain_test?sslmode=disable jobs: - setup: - name: Setup & Cache - runs-on: ubuntu-latest - outputs: - node-version: ${{ steps.setup-node.outputs.node-version }} - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Setup Node.js - id: setup-node - uses: actions/setup-node@v5 - with: - node-version: 20 - cache: 'npm' - - - name: Install dependencies - run: npm ci - - - name: Generate Prisma Client - run: npx prisma generate - - - name: Cache Prisma Client - uses: actions/cache@v4 - id: cache-prisma - with: - path: node_modules/.prisma - key: ${{ runner.os }}-prisma-${{ hashFiles('prisma/schema.prisma') }} - - lint: - name: Linting - needs: setup - runs-on: ubuntu-latest - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v5 - with: - node-version: 20 - cache: 'npm' - - - name: Install dependencies - run: npm ci - - - name: Run ESLint - run: npm run lint - - test-unit: - name: Unit Tests - needs: setup - runs-on: ubuntu-latest - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v5 - with: - node-version: 20 - cache: 'npm' - - - name: Install dependencies - run: npm ci - - - name: Run Unit Tests - run: npm run test:unit - env: - NODE_ENV: test - - test-integration: - name: Integration Tests - needs: setup + lint-and-build: + name: Lint & Build runs-on: ubuntu-latest + services: postgres: image: postgres:15 @@ -118,79 +23,13 @@ jobs: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres options: >- - --health-cmd "pg_isready -U postgres -d propchain_test" + --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 5432:5432 - redis: - image: redis:7 - options: >- - --health-cmd "redis-cli ping" - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 6379:6379 - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v5 - with: - node-version: 20 - cache: 'npm' - - - name: Install dependencies - run: npm ci - - - name: Wait for services - run: | - timeout 60 bash -c 'until nc -z localhost 5432; do sleep 1; done' - timeout 60 bash -c 'until nc -z localhost 6379; do sleep 1; done' - - name: Generate Prisma Client - run: npx prisma generate - - - name: Apply Prisma Migrations - run: npx prisma migrate deploy - - - name: Run Integration Tests - run: npm run test:integration - env: - NODE_ENV: test - DATABASE_URL: postgresql://postgres:postgres@localhost:5432/propchain_test - REDIS_URL: redis://localhost:6379 - - test-e2e: - name: E2E Tests - needs: setup - runs-on: ubuntu-latest - services: - postgres: - image: postgres:15 - env: - POSTGRES_DB: propchain_test - POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres - options: >- - --health-cmd "pg_isready -U postgres -d propchain_test" - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 5432:5432 - redis: - image: redis:7 - options: >- - --health-cmd "redis-cli ping" - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 6379:6379 steps: - name: Checkout Code uses: actions/checkout@v4 @@ -201,202 +40,23 @@ jobs: node-version: 20 cache: 'npm' - - name: Install dependencies + - name: Install Dependencies run: npm ci - - name: Wait for services - run: | - timeout 60 bash -c 'until nc -z localhost 5432; do sleep 1; done' - timeout 60 bash -c 'until nc -z localhost 6379; do sleep 1; done' - - name: Generate Prisma Client run: npx prisma generate - - name: Apply Prisma Migrations - run: npx prisma migrate deploy - - - name: Run E2E Tests - run: npm run test:e2e - env: - NODE_ENV: test - DATABASE_URL: postgresql://postgres:postgres@localhost:5432/propchain_test - REDIS_URL: redis://localhost:6379 - - test-security: - name: Security Tests - needs: setup - runs-on: ubuntu-latest - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v5 - with: - node-version: 20 - cache: 'npm' - - - name: Install dependencies - run: npm ci - - - name: Run Security Tests - run: npm run test:security - - test-migrations: - name: Migration Safety - needs: setup - runs-on: ubuntu-latest - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v5 - with: - node-version: 20 - cache: 'npm' - - - name: Install dependencies - run: npm ci - - - name: Run Migration Safety Checks - run: npm run migrate:test - - build: - name: Build (Production Target) - needs: [lint, test-unit, test-migrations] - runs-on: ubuntu-latest - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v5 - with: - node-version: 20 - cache: 'npm' - - - name: Install dependencies - run: npm ci - - - name: Generate Prisma Client - run: npx prisma generate + - name: Run Linter + run: npm run lint - name: Build Application run: npm run build - - name: Upload Build Artifact - uses: actions/upload-artifact@v4 - with: - name: build-artifact - path: dist/ - retention-days: 1 - - observability-test: - name: Observability Tests - needs: build - runs-on: ubuntu-latest - services: - postgres: - image: postgres:15 - env: - POSTGRES_PASSWORD: postgres - POSTGRES_USER: postgres - POSTGRES_DB: propchain_test - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 5432:5432 - redis: - image: redis:7 - options: >- - --health-cmd "redis-cli ping" - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 6379:6379 - jaeger: - image: jaegertracing/all-in-one:latest - options: >- - --health-cmd "wget --no-verbose --tries=1 --spider http://localhost:16686" - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 16686:16686 - - 4317:4317 - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v5 - with: - node-version: 20 - cache: 'npm' - - - name: Install dependencies - run: npm ci - - - name: Download Build Artifact - uses: actions/download-artifact@v4 - with: - name: build-artifact - path: dist - - - name: Wait for services - run: | - timeout 60 bash -c 'until nc -z localhost 5432; do sleep 1; done' - timeout 60 bash -c 'until nc -z localhost 6379; do sleep 1; done' - timeout 60 bash -c 'until nc -z localhost 16686; do sleep 1; done' - - - name: Start Application - run: | - npm run start & - sleep 30 - - - name: Test Observability Endpoints - run: | - curl -f http://localhost:3000/observability/health || exit 1 - curl -f http://localhost:3000/observability/metrics/current || exit 1 - curl -f http://localhost:3000/metrics || exit 1 - curl -f http://localhost:3000/observability/tracing/status || exit 1 - - - name: Test Metrics Collection - run: | - # Test that metrics are being collected - response=$(curl -s http://localhost:3000/metrics) - if [[ $response == *"http_request_duration_seconds"* ]]; then - echo "✅ HTTP metrics found" - else - echo "❌ HTTP metrics not found" - exit 1 - fi - - if [[ $response == *"system_cpu_usage_percent"* ]]; then - echo "✅ System metrics found" - else - echo "❌ System metrics not found" - exit 1 - fi - - env: - NODE_ENV: test - DATABASE_URL: postgresql://postgres:postgres@localhost:5432/propchain_test - REDIS_URL: redis://localhost:6379 - OTEL_SERVICE_NAME: propchain-backend-test - OTEL_EXPORTER_OTLP_ENDPOINT: http://localhost:4317 - METRICS_ENABLED: true - PERFORMANCE_MONITORING_ENABLED: true - - load-test: - name: Load Testing - needs: build + test: + name: Run Tests + needs: lint-and-build runs-on: ubuntu-latest + services: postgres: image: postgres:15 @@ -405,21 +65,13 @@ jobs: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres options: >- - --health-cmd "pg_isready -U postgres -d propchain_test" + --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 5432:5432 - redis: - image: redis:7 - options: >- - --health-cmd "redis-cli ping" - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 6379:6379 + steps: - name: Checkout Code uses: actions/checkout@v4 @@ -430,119 +82,44 @@ jobs: node-version: 20 cache: 'npm' - - name: Install dependencies + - name: Install Dependencies run: npm ci - - name: Download Build Artifact - uses: actions/download-artifact@v4 - with: - name: build-artifact - path: dist - - name: Generate Prisma Client run: npx prisma generate - - name: Apply Prisma Migrations - run: npx prisma migrate deploy - - - name: Wait for services - run: | - timeout 60 bash -c 'until nc -z localhost 5432; do sleep 1; done' - timeout 60 bash -c 'until nc -z localhost 6379; do sleep 1; done' - - - name: Start API in background - run: | - npm run start:ci > api.log 2>&1 & - echo $! > api.pid - - - name: Wait for API liveness - run: | - for attempt in {1..30}; do - if curl -fsS http://127.0.0.1:3000/api/v1/health/liveness > /dev/null; then - exit 0 - fi - sleep 2 - done - cat api.log - exit 1 - - - name: Run load tests - run: npm run loadtest:ci + - name: Run Tests + run: npm test env: - API_URL: http://127.0.0.1:3000 - HEALTH_PATH: /api/v1/health/liveness NODE_ENV: test DATABASE_URL: postgresql://postgres:postgres@localhost:5432/propchain_test - REDIS_URL: redis://localhost:6379 - - - name: Stop API - if: always() - run: | - if [ -f api.pid ]; then - kill "$(cat api.pid)" || true - fi - - - name: Upload API logs - if: failure() - uses: actions/upload-artifact@v4 - with: - name: load-test-api-log - path: api.log - - - name: Upload k6 results - uses: actions/upload-artifact@v4 - with: - name: k6-results - path: artifacts/k6-results.json deploy-staging: name: Deploy to Staging - needs: [build, test-integration, test-e2e, test-security, test-migrations, observability-test] - if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop') + needs: [lint-and-build, test] + if: github.ref == 'refs/heads/develop' && github.event_name == 'push' runs-on: ubuntu-latest environment: staging + steps: - name: Checkout Code uses: actions/checkout@v4 - - name: Download Build Artifact - uses: actions/download-artifact@v4 - with: - name: build-artifact - path: dist - - - name: Deploy to Staging Server - run: echo "🚀 Deploying to staging environment... (Placeholder)" - # Actual deployment logic would go here: - # - npm run deploy:staging - # - scp -r dist/* user@staging-host:/var/www/propchain - # - heroku/deploy-action@v5 - # - aws ecs update-service... + - name: Deploy to Staging + run: echo "Deploying to staging environment..." + # Add your deployment steps here deploy-production: name: Deploy to Production - needs: [deploy-staging] - if: github.event_name == 'push' && github.ref == 'refs/heads/main' + needs: [lint-and-build, test] + if: github.ref == 'refs/heads/main' && github.event_name == 'push' runs-on: ubuntu-latest - environment: - name: production - url: https://api.propchain.com + environment: production + steps: - name: Checkout Code uses: actions/checkout@v4 - - name: Download Build Artifact - uses: actions/download-artifact@v4 - with: - name: build-artifact - path: dist - - - name: Run Production Migrations - run: echo "🛠 Running production database migrations... (Placeholder)" - # run: npx prisma migrate deploy - - - name: Deploy to Production Cluster - run: echo "🚀 Deploying to production environment... (Blue/Green Strategy Placeholder)" - # Actual deployment strategy (Blue/Green or Canary): - # - Implement traffic routing switch - # - Health checks check \ No newline at end of file + - name: Deploy to Production + run: echo "Deploying to production environment..." + # Add your deployment steps here diff --git a/.gitignore b/.gitignore index 8c8b46eb..0a58c354 100644 --- a/.gitignore +++ b/.gitignore @@ -1,40 +1,26 @@ # Dependencies node_modules/ -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* +.pnp +.pnp.js # Build outputs dist/ build/ -.next/ -out/ +*.tsbuildinfo -# Environment variables +# Environment files .env .env.local -.env.development.local -.env.test.local -.env.production.local -.env.example -src/backup-recovery/.env.example +.env.*.local +!.env.example -# IDE and editor files +# IDE .vscode/ .idea/ *.swp *.swo *~ - -# OS generated files .DS_Store -.DS_Store? -._* -.Spotlight-V100 -.Trashes -ehthumbs.db -Thumbs.db # Logs logs/ @@ -43,26 +29,18 @@ npm-debug.log* yarn-debug.log* yarn-error.log* lerna-debug.log* +pnpm-debug.log* -# Runtime data -pids/ -*.pid -*.seed -*.pid.lock - -# Coverage directory used by tools like istanbul +# Testing coverage/ -*.lcov - -# nyc test coverage .nyc_output/ -# Dependency directories -node_modules/ -jspm_packages/ +# Prisma +prisma/migrations/ +!prisma/migrations/.gitkeep -# TypeScript cache -*.tsbuildinfo +# OS files +Thumbs.db # Optional npm cache directory .npm @@ -70,151 +48,21 @@ jspm_packages/ # Optional eslint cache .eslintcache -# Optional stylelint cache -.stylelintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - # Optional REPL history .node_repl_history # Output of 'npm pack' *.tgz -# Yarn Integrity file +# Yarn .yarn-integrity - -# parcel-bundler cache (https://parceljs.org/) -.cache -.parcel-cache - -# Next.js build output -.next - -# Nuxt.js build / generate output -.nuxt -dist - -# Gatsby files -.cache/ -public - -# Storybook build outputs -.out -.storybook-out - -# Temporary folders -tmp/ -temp/ - -# Database -*.db -*.sqlite -*.sqlite3 - -# Prisma -# Keep migrations in git so schema/index changes are deployable. -# (Avoid ignoring `prisma/migrations/`.) - -# Docker -.dockerignore - -# Kubernetes -*.kubeconfig - -# Terraform -*.tfstate -*.tfstate.* -.terraform/ - -# Ansible -*.retry -inventory/ - -# Backup files -*.bak -*.backup - -# Test files -test-results/ -playwright-report/ -test-results.xml - -# Sentry -.sentryclirc - -# Local development -.local/ - -# Uploads -uploads/ -static/ - -# Certificates -*.pem -*.key -*.crt -*.p12 - -# Configuration files with secrets -config/local.json -config/production.json - -# Hardhat -# cache/ # Commented out to allow source code cache directory -artifacts/ -typechain-types/ - -# Foundry -lib/ -out/ - -# Rust -target/ -Cargo.lock - -# Python (if any) -__pycache__/ -*.py[cod] -*$py.class -*.so -.Python -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Jupyter Notebook -.ipynb_checkpoints - -# pyenv -.python-version - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json +.pnp.* +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz + +# Package manager files +package-lock.json +yarn.lock +pnpm-lock.yaml diff --git a/.npmrc b/.npmrc deleted file mode 100644 index 2bd9a1fe..00000000 --- a/.npmrc +++ /dev/null @@ -1,2 +0,0 @@ -legacy-peer-deps=true -audit-level=low diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index b602cce1..00000000 --- a/.prettierignore +++ /dev/null @@ -1,40 +0,0 @@ -# Dependencies -node_modules/ -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Build outputs -dist/ -build/ -coverage/ - -# Environment files -.env -.env.local -.env.development.local -.env.test.local -.env.production.local - -# IDE files -.vscode/ -.idea/ -*.swp -*.swo -*~ - -# OS files -.DS_Store -Thumbs.db - -# Logs -logs/ -*.log - -# Database -*.db -*.sqlite - -# Temporary files -tmp/ -temp/ diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index b695859b..00000000 --- a/.prettierrc +++ /dev/null @@ -1,14 +0,0 @@ -{ - "semi": true, - "trailingComma": "all", - "singleQuote": true, - "printWidth": 120, - "tabWidth": 2, - "useTabs": false, - "bracketSpacing": true, - "arrowParens": "avoid", - "endOfLine": "lf", - "quoteProps": "as-needed", - "bracketSameLine": false, - "proseWrap": "preserve" -} diff --git a/COMPRESSION_PR_DESCRIPTION.md b/COMPRESSION_PR_DESCRIPTION.md deleted file mode 100644 index 3a3486c0..00000000 --- a/COMPRESSION_PR_DESCRIPTION.md +++ /dev/null @@ -1,246 +0,0 @@ -# 🚀 Response Compression Implementation - -## 📋 Summary -Implements comprehensive response compression system to address large API response sizes, significantly improving bandwidth efficiency and client performance. - -## 🎯 Issue Addressed -**Missing Response Compression** - Large API responses not properly compressed, leading to inefficient bandwidth usage and slower client performance. - -## ✅ Acceptance Criteria Met - -### ✅ Configure compression middleware -- Enhanced compression middleware with configurable options -- Environment-based configuration with validation -- Intelligent compression level management (1-9) -- Threshold-based compression to avoid unnecessary CPU usage - -### ✅ Implement response size monitoring -- Real-time metrics collection for compression performance -- Compression ratio tracking per endpoint and content type -- Memory-efficient metrics storage with automatic cleanup -- Detailed monitoring endpoints for observability - -### ✅ Add compression for specific content types -- Configurable content-type filtering via environment variables -- Smart compression for text-based formats (JSON, XML, JavaScript, CSS, SVG) -- Exclusion of binary formats that don't benefit from compression -- Customizable content-type lists per environment - -## 🔧 Technical Implementation - -### Core Components - -1. **Enhanced Compression Middleware** (`src/middleware/compression.middleware.ts`) - - Configurable compression options with environment validation - - Real-time response size monitoring and metrics collection - - Intelligent content-type filtering - - Memory-efficient metrics storage with automatic cleanup - -2. **Compression Controller** (`src/common/controllers/compression.controller.ts`) - - REST API endpoints for compression metrics and monitoring - - Health check functionality with performance recommendations - - Metrics management endpoints - -3. **Compression Module** (`src/common/modules/compression.module.ts`) - - NestJS module structure with proper dependency injection - - Integration with existing application architecture - -4. **Configuration Validation** (`src/config/validation/config.validation.ts`) - - Added compression configuration schema validation - - Environment variable validation and defaults - -### New API Endpoints - -``` -GET /api/v1/compression/metrics -- Returns detailed compression metrics -- Includes individual request metrics, averages, and totals -- Provides compression ratio and bandwidth savings data - -GET /api/v1/compression/health -- Compression system health status -- Performance recommendations -- Configuration validation results - -GET /api/v1/compression/clear-metrics -- Clears all stored compression metrics -- Useful for testing and maintenance -``` - -### Configuration Options - -```bash -# Enable/disable compression -COMPRESSION_ENABLED=true - -# Compression level (1-9, where 9 is maximum compression) -COMPRESSION_LEVEL=6 - -# Minimum response size to compress (in bytes) -COMPRESSION_THRESHOLD=1024 - -# Content types to compress (comma-separated) -COMPRESSION_CONTENT_TYPES=text/,application/json,application/javascript,application/xml,application/rss+xml,application/x-javascript,image/svg+xml,font/,application/wasm -``` - -## 📊 Performance Benefits - -### Expected Compression Ratios -- **JSON responses**: 60-80% size reduction -- **HTML/CSS**: 70-85% size reduction -- **JavaScript**: 65-75% size reduction -- **XML/SVG**: 80-90% size reduction - -### Bandwidth and Performance Impact -- **Large API responses**: Significant reduction in transfer size -- **Mobile clients**: Improved performance on slower connections -- **CDN costs**: Reduced bandwidth usage and operational costs -- **Server load**: Optimized CPU vs bandwidth trade-off - -## 🧪 Testing - -### Comprehensive Test Coverage -- **Unit Tests** (`src/common/tests/compression.spec.ts`) - - Compression service functionality - - Metrics recording and retrieval - - Content-type filtering logic - - Configuration validation - - Memory management (metrics cleanup) - -### Test Scenarios Covered -- Compression options configuration -- Metrics collection and aggregation -- Content-type filtering validation -- Threshold-based compression logic -- Memory leak prevention -- Error handling and edge cases - -## 🔒 Security Considerations - -### Content Security -- **Input validation** for all configuration values -- **Safe content-type filtering** to avoid compression of sensitive data -- **Memory limits** to prevent DoS attacks via metrics storage -- **Configuration validation** to prevent misconfiguration - -### Performance Security -- **CPU usage monitoring** to prevent compression-based attacks -- **Threshold enforcement** to avoid unnecessary compression overhead -- **Rate limiting integration** for compression monitoring endpoints - -## 📈 Monitoring and Observability - -### Metrics Collected -- Original response size -- Compressed response size -- Compression ratio -- Request endpoint and HTTP method -- Content type -- Timestamp - -### Health Monitoring -- Compression ratio thresholds and alerts -- Performance recommendations -- Error detection and reporting -- Configuration validation status - -## 🔄 Backward Compatibility - -- **Zero breaking changes** to existing API endpoints -- **Optional configuration** with sensible defaults -- **Gradual rollout** capability via feature flags -- **Graceful degradation** if compression fails - -## 📁 Files Modified - -### New Files Created -- `src/middleware/compression.middleware.ts` - Enhanced compression middleware -- `src/common/controllers/compression.controller.ts` - Monitoring endpoints -- `src/common/modules/compression.module.ts` - NestJS module -- `src/common/tests/compression.spec.ts` - Unit tests -- `COMPRESSION_FEATURE.md` - Detailed documentation - -### Modified Files -- `src/main.ts` - Integration with enhanced compression middleware -- `src/app.module.ts` - Module registration and controller setup -- `src/config/validation/config.validation.ts` - Configuration schema -- `.env.development` - Environment configuration variables - -## 🚀 Deployment Considerations - -### Environment Configuration -- **Development**: Compression enabled with moderate settings -- **Staging**: Production-like configuration for testing -- **Production**: Optimized settings for maximum efficiency - -### Performance Tuning -- **Compression level**: Adjust based on server CPU capacity -- **Threshold**: Configure based on typical response sizes -- **Content types**: Customize per application requirements - -## 📚 Documentation - -### Comprehensive Documentation -- **Feature documentation** (`COMPRESSION_FEATURE.md`) -- **API endpoint documentation** with examples -- **Configuration guide** with environment variables -- **Testing documentation** with coverage details -- **Performance benchmarks** and expected benefits - -## 🎯 Impact Assessment - -### Immediate Benefits -- **Reduced bandwidth usage** for all API responses -- **Faster response times** for clients -- **Improved mobile experience** on slower connections -- **Lower infrastructure costs** due to reduced data transfer - -### Long-term Benefits -- **Scalability improvements** for growing user base -- **Better SEO** due to faster page loads -- **Enhanced user experience** across all devices -- **Operational cost savings** on bandwidth and CDN - -## 🔮 Future Enhancements - -### Potential Improvements -1. **Brotli compression** support for better compression ratios -2. **Dynamic compression level adjustment** based on server load -3. **Per-client compression preferences** and optimization -4. **Advanced caching strategies** for compressed content -5. **Real-time compression dashboard** with Grafana integration - -### Monitoring Enhancements -1. **Prometheus metrics integration** for advanced monitoring -2. **Grafana dashboard templates** for visualization -3. **Alert rules** for compression performance anomalies -4. **Historical trend analysis** and reporting - -## ✅ Validation - -### Acceptance Criteria Validation -- ✅ **Compression middleware configured** with environment-based settings -- ✅ **Response size monitoring implemented** with comprehensive metrics -- ✅ **Content-type specific compression** added with configurable filtering - -### Quality Assurance -- ✅ **Unit tests written** with comprehensive coverage -- ✅ **Integration tested** with existing application -- ✅ **Performance benchmarked** with expected improvements -- ✅ **Security reviewed** for potential vulnerabilities -- ✅ **Documentation completed** with user guides - ---- - -## 🎉 Summary - -This implementation provides a production-ready, comprehensive solution to the missing response compression issue. The system is: - -- **Configurable**: Environment-based configuration with validation -- **Monitorable**: Real-time metrics and health monitoring -- **Performant**: Optimized compression with intelligent filtering -- **Secure**: Built-in security considerations and protections -- **Testable**: Comprehensive test coverage and validation -- **Documented**: Detailed documentation and usage guides - -The solution delivers significant performance improvements while maintaining backward compatibility and providing extensive monitoring capabilities. diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index b9710139..00000000 --- a/Dockerfile +++ /dev/null @@ -1,55 +0,0 @@ -# Multi-stage build for production optimization -FROM node:18-alpine AS base - -# Install dependencies only when needed -FROM base AS deps -RUN apk add --no-cache libc6-compat postgresql-client bash -WORKDIR /app - -# Install dependencies based on the preferred package manager -COPY package.json package-lock.json* ./ -RUN npm ci --only=production - -# Rebuild the source code only when needed -FROM base AS builder -WORKDIR /app -COPY --from=deps /app/node_modules ./node_modules -COPY . . - -# Build the application -RUN npm run build - -# Production image, copy all the files and run the app -FROM base AS runner -WORKDIR /app - -ENV NODE_ENV=production - -# Create a non-root user -RUN addgroup --system --gid 1001 nodejs -RUN adduser --system --uid 1001 nestjs - -# Copy the built application -COPY --from=builder --chown=nestjs:nodejs /app/dist ./dist -COPY --from=builder --chown=nestjs:nodejs /app/node_modules ./node_modules -COPY --from=builder --chown=nestjs:nodejs /app/package.json ./package.json - -# Copy scripts for backups -COPY --from=builder --chown=nestjs:nodejs /app/scripts ./scripts -RUN chmod +x scripts/*.sh - -# Create logs directory -RUN mkdir -p logs && chown nestjs:nodejs logs - -# Switch to non-root user -USER nestjs - -# Expose port -EXPOSE 3000 - -# Health check -HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ - CMD curl -f http://localhost:3000/api/health || exit 1 - -# Start the application -CMD ["npm", "start"] diff --git a/GITHUB_PR_DESCRIPTION.md b/GITHUB_PR_DESCRIPTION.md deleted file mode 100644 index 59d563bb..00000000 --- a/GITHUB_PR_DESCRIPTION.md +++ /dev/null @@ -1,241 +0,0 @@ -# 🏥 Comprehensive Health Check Implementation - -**Closes #127: Missing Health Check Endpoints** - -## 📋 Summary - -This PR implements a comprehensive health check system for the PropChain-BackEnd application, providing enterprise-grade monitoring capabilities for all system components, dependencies, and resources. - -## ✨ Features Implemented - -### 🔍 **Enhanced Health Check System** -- **Multi-level Health Checks**: Basic, detailed, and comprehensive endpoints -- **Real-time Monitoring**: Live status updates for all services -- **Response Time Tracking**: Performance metrics for all health checks -- **Error Diagnostics**: Detailed error reporting with context - -### 📊 **New Health Indicators** -- **Memory Health**: Heap usage, system memory, and external memory monitoring -- **CPU Health**: Process usage, load averages, and system information -- **Disk Health**: Storage accessibility and write operations testing -- **Dependencies Health**: Configurable external service monitoring - -### 🔧 **Enhanced Existing Indicators** -- **Database Health**: Connection pool monitoring, table counts, and detailed diagnostics -- **Redis Health**: Read/write tests, server info, and memory statistics -- **Blockchain Health**: Gas price monitoring, block data, and balance queries - -### 📈 **Analytics & Monitoring** -- **Health Analytics Service**: Real-time metrics collection and storage -- **Historical Tracking**: Last 1000 health check records with filtering -- **Service Statistics**: Individual success rates and performance metrics -- **Automated Cleanup**: Periodic removal of old metrics - -### ⏰ **Scheduled Health Checks** -- **Basic Checks**: Every 5 minutes (core services) -- **Extended Checks**: Every 30 minutes (all services) -- **Dependency Checks**: Every hour (external services) -- **Cleanup Tasks**: Daily at midnight - -## 🚀 **New Endpoints** - -| Endpoint | Method | Description | -|-----------|---------|-------------| -| `/health` | GET | Basic health check (database, Redis) | -| `/health/detailed` | GET | Comprehensive service health | -| `/health/comprehensive` | GET | Full health with analytics | -| `/health/liveness` | GET | Kubernetes liveness probe | -| `/health/readiness` | GET | Kubernetes readiness probe | -| `/health/analytics` | GET | Health metrics and statistics | -| `/health/analytics/clear` | GET | Clear analytics data | -| `/health/dependencies` | GET | View configured dependencies | -| `/health/trigger` | POST | Manual health check trigger | - -## 📁 **Files Added** - -### New Services -- `src/health/health-analytics.service.ts` - Analytics and metrics collection -- `src/health/health-scheduler.service.ts` - Automated health checks - -### New Health Indicators -- `src/health/indicators/memory.health.ts` - Memory monitoring -- `src/health/indicators/cpu.health.ts` - CPU monitoring -- `src/health/indicators/disk.health.ts` - Disk monitoring -- `src/health/indicators/dependencies.health.ts` - External dependencies - -### Testing & Documentation -- `test/health/health.controller.spec.ts` - Comprehensive test suite -- `docs/health-checks.md` - Complete documentation - -## 📝 **Files Modified** - -### Enhanced Health Components -- `src/health/health.controller.ts` - Added new endpoints and analytics -- `src/health/health.module.ts` - Added new providers and imports -- `src/health/indicators/database.health.ts` - Enhanced with detailed diagnostics -- `src/health/indicators/redis.health.ts` - Enhanced with comprehensive monitoring -- `src/health/indicators/blockchain.health.ts` - Enhanced with additional checks - -## ✅ **Acceptance Criteria Met** - -### 🎯 **Implement Detailed Health Checks** -- [x] Comprehensive monitoring of all system components -- [x] Enhanced diagnostics with response times -- [x] Detailed error reporting and context -- [x] Performance metrics and thresholds - -### 🔗 **Add Dependency Health Monitoring** -- [x] Configurable external service monitoring -- [x] HTTP-based health checks with timeouts -- [x] Support for multiple external APIs -- [x] Dynamic dependency configuration - -### 📊 **Implement Health Check Analytics** -- [x] Real-time metrics collection -- [x] Historical data tracking -- [x] Service-specific statistics -- [x] Analytics endpoints for monitoring - -## ⚙️ **Configuration** - -Add these environment variables to your `.env` file: - -```bash -# Health Check Dependencies (JSON array) -HEALTH_CHECK_DEPENDENCIES=[ - { - "name": "valuation-provider", - "url": "https://api.valuation-service.com/v1/health", - "timeout": 5000, - "method": "GET", - "expectedStatus": 200 - }, - { - "name": "blockchain-rpc", - "url": "https://eth-mainnet.alchemyapi.io/v2/demo", - "timeout": 3000, - "method": "POST", - "headers": { - "Content-Type": "application/json" - } - } -] - -# Existing Configuration (enhanced) -DATABASE_URL=postgresql://user:password@localhost:5432/propchain -REDIS_HOST=localhost -REDIS_PORT=6379 -REDIS_PASSWORD=your_password -REDIS_DB=0 -RPC_URL=https://eth-mainnet.alchemyapi.io/v2/your_api_key -``` - -## 🧪 **Testing** - -```bash -# Run health check tests -npm run test -- --testPathPattern=health - -# Run integration tests -npm run test:integration - -# Run all tests -npm run test:all -``` - -## ☸️ **Kubernetes Integration** - -The health endpoints are production-ready for Kubernetes: - -```yaml -livenessProbe: - httpGet: - path: /health/liveness - port: 3000 - initialDelaySeconds: 30 - periodSeconds: 10 - -readinessProbe: - httpGet: - path: /health/readiness - port: 3000 - initialDelaySeconds: 5 - periodSeconds: 5 -``` - -## 📊 **Performance Impact** - -| Metric | Impact | Description | -|---------|---------|-------------| -| Response Time | Minimal | Health checks are lightweight and fast | -| Memory Usage | Low | Metrics limited to 1000 records | -| CPU Usage | Minimal | Efficient health check algorithms | -| Network Overhead | Low | Configurable timeouts and intervals | - -## 🔒 **Security Considerations** - -- **Endpoint Security**: Health endpoints should be secured in production -- **IP Whitelisting**: Consider restricting access to monitoring systems -- **Rate Limiting**: Apply to prevent abuse -- **Data Filtering**: Sensitive information is filtered from responses - -## 🚨 **Breaking Changes** - -**None** - All existing health endpoints remain fully functional with enhanced functionality. - -## 📈 **Monitoring Integration** - -### Prometheus Metrics -Health check metrics can be integrated with existing Prometheus setup using `@willsoto/nestjs-prometheus`. - -### Alerting Rules -Configure alerts for: -- Health check failures (> 3 consecutive failures) -- High response times (> 1000ms) -- Resource threshold breaches -- Dependency unavailability - -## 🔗 **Related Issues** - -- **Closes #127**: Missing Health Check Endpoints -- **Enhances**: Production monitoring capabilities -- **Improves**: System observability and debugging - -## 📋 **Review Checklist** - -- [x] Code follows project style guidelines -- [x] All tests pass -- [x] Documentation is comprehensive -- [x] Environment variables are documented -- [x] Security considerations are addressed -- [x] Performance impact is minimal -- [x] Error handling is comprehensive -- [x] Logging is appropriate -- [x] Kubernetes integration is ready -- [x] Backward compatibility is maintained - -## 🎉 **Benefits** - -### Operational Excellence -- **Proactive Monitoring**: Early detection of system issues -- **Dependency Visibility**: Clear insight into external service health -- **Performance Tracking**: Response times and performance metrics -- **Automated Alerts**: Configurable notification systems - -### Developer Experience -- **Easy Integration**: Simple API for health check consumption -- **Comprehensive Documentation**: Detailed setup and usage guides -- **Debugging Support**: Detailed error messages and diagnostics -- **Testing Coverage**: Full test suite for reliability - -### Production Readiness -- **Scalability**: Designed for high-traffic environments -- **Reliability**: Robust error handling and recovery -- **Compliance**: Kubernetes and container orchestration support -- **Monitoring**: Enterprise-grade observability - ---- - -**🚀 Ready for Production Deployment** - -This implementation provides enterprise-grade health monitoring that addresses all requirements from issue #127 and establishes a robust foundation for operational excellence. diff --git a/PR_DESCRIPTION.md b/PR_DESCRIPTION.md deleted file mode 100644 index 93c915c0..00000000 --- a/PR_DESCRIPTION.md +++ /dev/null @@ -1,252 +0,0 @@ -# Pull Request: Comprehensive Observability Features Implementation - -## Summary -This PR implements comprehensive observability features for the PropChain-BackEnd application, addressing issue #128: Missing Observability Features. - -## Changes Made - -### 🔍 Distributed Tracing Implementation -- **OpenTelemetry Integration**: Production-ready distributed tracing with OTLP exporters -- **Auto-Instrumentation**: Automatic trace generation for HTTP requests, database queries, and blockchain operations -- **Custom Spans**: Easy-to-use API for creating business-specific traces -- **Resource Detection**: Automatic service metadata and environment detection -- **Export Configuration**: Support for Jaeger, Tempo, and other OTLP-compatible backends - -### 📊 Custom Metrics Collection -- **HTTP Metrics**: Request duration, count, size tracking with detailed labels -- **Business Metrics**: Database query duration, blockchain operation timing, cache performance -- **System Metrics**: CPU, memory, disk, and network monitoring -- **Error Tracking**: Error rate monitoring by type and endpoint -- **Prometheus Integration**: Standard metrics endpoint with custom collectors - -### 🚀 Performance Monitoring -- **Real-time Monitoring**: System and application performance metrics collection -- **Health Assessment**: Automated health status (healthy/warning/critical) with configurable thresholds -- **Historical Data**: Metrics retention and historical analysis -- **Scheduled Collection**: Automated metrics collection with cleanup -- **Alert Thresholds**: Configurable alerts for CPU, memory, error rate, and response time - -### 🌐 Observability API Endpoints -- `GET /metrics` - Prometheus metrics endpoint -- `GET /observability/health` - Detailed health status with performance metrics -- `GET /observability/metrics/current` - Current performance metrics snapshot -- `GET /observability/metrics/history` - Historical metrics data -- `GET /observability/metrics/average` - Average metrics over time period -- `GET /observability/tracing/status` - Tracing service status - -### ⚙️ Configuration & Documentation -- **Environment Configuration**: Comprehensive observability settings -- **Documentation**: Complete setup guide, usage examples, and best practices -- **Integration Guides**: Jaeger, Prometheus, and Grafana setup instructions -- **Troubleshooting Guide**: Common issues and solutions - -## Files Added - -### Core Services -- `src/observability/tracing.service.ts` - Enhanced OpenTelemetry tracing service -- `src/observability/metrics.interceptor.ts` - Comprehensive metrics collection -- `src/observability/performance-monitor.service.ts` - Real-time performance monitoring -- `src/observability/observability.controller.ts` - Observability API endpoints -- `src/observability/observability.module.ts` - NestJS module configuration - -### Configuration -- `src/config/observability.config.ts` - Observability configuration settings -- `docs/observability.md` - Complete documentation and usage guide - -### Environment -- `.env.development` - Updated with observability configuration - -## Files Modified - -### Core Application -- `src/app.module.ts` - Added observability module and configuration -- `package.json` - Added OpenTelemetry exporter dependencies - -## Acceptance Criteria Met - -✅ **Implement distributed tracing** -- OpenTelemetry integration with auto-instrumentation -- Configurable OTLP exporters (Jaeger, Tempo, etc.) -- Custom span creation utilities -- Semantic conventions and resource detection -- Graceful shutdown handling - -✅ **Add custom metrics** -- HTTP request/response metrics with detailed labels -- Database query duration tracking -- Blockchain operation monitoring -- Cache performance metrics -- Error rate and connection tracking -- Prometheus integration with custom collectors - -✅ **Implement performance monitoring** -- Real-time system metrics (CPU, memory, network) -- Application health monitoring with configurable thresholds -- Historical data retention and analysis -- Health status assessment (healthy/warning/critical) -- Automated metrics collection and cleanup - -## Configuration - -Add these environment variables to your `.env` file: - -```bash -# OpenTelemetry Tracing -OTEL_SERVICE_NAME=propchain-backend -OTEL_SERVICE_VERSION=1.0.0 -OTEL_ENABLED=true -OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 -OTEL_SAMPLING_RATE=1.0 - -# Metrics -METRICS_ENABLED=true -METRICS_PATH=/metrics -METRICS_PORT=9090 - -# Performance Monitoring -PERFORMANCE_MONITORING_ENABLED=true -PERFORMANCE_MONITORING_INTERVAL=30000 -PERFORMANCE_METRICS_RETENTION=86400000 - -# Alert Thresholds -CPU_ALERT_THRESHOLD=90 -MEMORY_ALERT_THRESHOLD=90 -ERROR_RATE_ALERT_THRESHOLD=5 -RESPONSE_TIME_ALERT_THRESHOLD=5000 -``` - -## Quick Start - -### 1. Install Dependencies -```bash -npm install -``` - -### 2. Start Jaeger (Optional) -```bash -docker run -d \ - --name jaeger \ - -p 16686:16686 \ - -p 4317:4317 \ - jaegertracing/all-in-one:latest -``` - -### 3. Start Application -```bash -npm run start:dev -``` - -### 4. View Metrics -- **Prometheus Metrics**: http://localhost:3000/metrics -- **Health Status**: http://localhost:3000/observability/health -- **Current Metrics**: http://localhost:3000/observability/metrics/current -- **Jaeger UI**: http://localhost:16686 (if running) - -## Integration Examples - -### Adding Custom Metrics -```typescript -@Injectable() -export class PropertyService { - constructor(private metricsInterceptor: MetricsInterceptor) {} - - async createProperty(data: CreatePropertyDto) { - const start = Date.now(); - - try { - const property = await this.repository.create(data); - - this.metricsInterceptor.recordCustomMetric( - 'property_creation_duration_seconds', - (Date.now() - start) / 1000, - { status: 'success' } - ); - - return property; - } catch (error) { - this.metricsInterceptor.recordCustomMetric( - 'property_creation_duration_seconds', - (Date.now() - start) / 1000, - { status: 'error', error_type: error.constructor.name } - ); - throw error; - } - } -} -``` - -### Adding Custom Spans -```typescript -@Injectable() -export class BlockchainService { - constructor(private tracingService: TracingService) {} - - async transferProperty(from: string, to: string, propertyId: string) { - const span = this.tracingService.createSpan('property-transfer', { - from, to, propertyId, - network: process.env.BLOCKCHAIN_NETWORK, - }); - - try { - const result = await this.contract.transfer(from, to, propertyId); - span.setAttributes({ - transactionHash: result.hash, - gasUsed: result.gasUsed.toString(), - }); - return result; - } catch (error) { - span.recordException(error); - throw error; - } finally { - span.end(); - } - } -} -``` - -## Testing - -```bash -# Run unit tests -npm run test:unit - -# Run integration tests -npm run test:integration - -# Run all tests -npm run test:all -``` - -## Performance Impact - -- **Low Overhead**: Optimized metrics collection with minimal performance impact -- **Configurable Sampling**: Adjustable tracing sampling rates for production -- **Batch Processing**: Efficient batch processing for metrics export -- **Memory Management**: Automatic cleanup of historical data - -## Security Considerations - -- **Secure Endpoints**: Metrics endpoints should be secured in production -- **Data Sanitization**: Sensitive data is filtered from traces and metrics -- **Access Control**: Admin-only access to detailed observability data -- **Rate Limiting**: Consider rate limiting for metrics endpoints - -## Breaking Changes - -None. All existing functionality remains unchanged. New observability features are additive. - -## Related Issues - -Closes #128: Missing Observability Features - -## Review Checklist - -- [ ] Code follows project style guidelines -- [ ] All tests pass -- [ ] Documentation is comprehensive -- [ ] Environment variables are documented -- [ ] Security considerations are addressed -- [ ] Performance impact is minimal -- [ ] Error handling is comprehensive -- [ ] Integration examples are provided -- [ ] Troubleshooting guide is included diff --git a/README.md b/README.md new file mode 100644 index 00000000..98e949ab --- /dev/null +++ b/README.md @@ -0,0 +1,173 @@ +# PropChain - Blockchain-Powered Real Estate Platform + +A modern, scalable backend API for real estate transactions built with NestJS and PostgreSQL. + +## 🚀 Features + +- **User Management** - Registration, authentication, and profile management +- **Property Listings** - Create, manage, and search property listings +- **Transaction Tracking** - Record and track real estate transactions +- **Document Management** - Store and manage property-related documents +- **Clean Architecture** - Modular, testable, and maintainable code structure +- **CI/CD Ready** - Automated testing and deployment pipeline + +## 📋 Prerequisites + +- Node.js >= 18.0.0 +- PostgreSQL >= 14 +- npm >= 8.0.0 + +## 🛠️ Installation + +```bash +# Install dependencies +npm install + +# Copy environment file +cp .env.example .env + +# Set up your database URL in .env file +``` + +## 🗄️ Database Setup + +```bash +# Generate Prisma Client +npm run db:generate + +# Run migrations +npm run migrate + +# (Optional) Seed database +npm run db:seed +``` + +## 🏃 Running the App + +```bash +# Development mode +npm run start:dev + +# Production mode +npm run build +npm run start:prod +``` + +## 🧪 Testing + +```bash +# Unit tests +npm test + +# Test coverage +npm run test:cov + +# Watch mode +npm run test:watch +``` + +## 📁 Project Structure + +``` +src/ +├── database/ # Database configuration and Prisma service +├── users/ # User management module +├── properties/ # Property listings module +├── app.module.ts # Main application module +├── app.controller.ts # App controller with health check +└── main.ts # Application entry point + +prisma/ +├── schema.prisma # Database schema +└── seed.ts # Database seeding +``` + +## 🔧 Available Scripts + +| Command | Description | +|---------|-------------| +| `npm run build` | Build the application | +| `npm run start:dev` | Start in development mode with watch | +| `npm run start:prod` | Start in production mode | +| `npm run lint` | Run ESLint with auto-fix | +| `npm run format` | Format code with Prettier | +| `npm test` | Run tests | +| `npm run test:cov` | Run tests with coverage | +| `npm run migrate` | Run database migrations | +| `npm run migrate:deploy` | Deploy migrations to production | +| `npm run db:generate` | Generate Prisma Client | +| `npm run db:studio` | Open Prisma Studio | + +## 📊 Database Schema + +### Core Models + +- **User** - Platform users (buyers, sellers, agents, admins) +- **Property** - Real estate listings with detailed information +- **Transaction** - Property transactions with blockchain integration +- **Document** - Property-related documents and files + +## 🔐 Environment Variables + +Create a `.env` file based on `.env.example`: + +```env +DATABASE_URL=postgresql://user:password@localhost:5432/propchain +PORT=3000 +JWT_SECRET=your-secret-key +``` + +## 🚢 Deployment + +The CI/CD pipeline is configured in `.github/workflows/ci.yml`: + +- **Develop branch** → Deploys to staging +- **Main branch** → Deploys to production + +### Manual Deployment + +```bash +# Build for production +npm run build + +# Run migrations +npm run migrate:deploy + +# Start application +npm run start:prod +``` + +## 📝 API Endpoints + +### Health Check +- `GET /api/health` - Application health status + +### Users +- `POST /api/users` - Create user +- `GET /api/users` - List all users +- `GET /api/users/:id` - Get user by ID +- `PUT /api/users/:id` - Update user +- `DELETE /api/users/:id` - Delete user + +### Properties +- `POST /api/properties` - Create property +- `GET /api/properties` - List all properties +- `GET /api/properties/:id` - Get property by ID +- `PUT /api/properties/:id` - Update property +- `DELETE /api/properties/:id` - Delete property + +## 🤝 Contributing + +1. Fork the repository +2. Create your feature branch (`git checkout -b feature/amazing-feature`) +3. Commit your changes (`git commit -m 'Add amazing feature'`) +4. Push to the branch (`git push origin feature/amazing-feature`) +5. Open a Pull Request + +## 📄 License + +This project is licensed under the MIT License. + +## 👥 Support + +For support, email support@propchain.com or join our Slack channel. diff --git a/TESTING_IMPLEMENTATION.md b/TESTING_IMPLEMENTATION.md deleted file mode 100644 index 5a1e890c..00000000 --- a/TESTING_IMPLEMENTATION.md +++ /dev/null @@ -1,296 +0,0 @@ -# Advanced API Testing and Quality Assurance Implementation - -## 🎯 Issue #240 Solution - -This implementation addresses issue #240 by providing a comprehensive API testing and quality assurance system for the PropChain backend. - -## 📁 Files Created - -### Core Testing Components -- ✅ `src/testing/TestGenerator.ts` - Automated API test generation -- ✅ `src/testing/ContractTester.ts` - Contract testing framework -- ✅ `src/testing/PerformanceBenchmark.ts` - Performance benchmarking -- ✅ `src/services/TestingService.ts` - Main testing orchestration service - -### Supporting Files -- ✅ `src/testing/testing.module.ts` - NestJS module for testing services -- ✅ `src/testing/testing.controller.ts` - REST API controller for testing -- ✅ `test-suites/propchain-api-tests.json` - Example test suite configuration -- ✅ `scripts/run-comprehensive-tests.ts` - Comprehensive test execution script -- ✅ `docs/testing.md` - Comprehensive documentation - -## 🚀 Key Features Implemented - -### 1. Automated API Test Generation -- **OpenAPI/Swagger Integration**: Generate tests automatically from API specifications -- **Mock Data Strategies**: Random, realistic, and minimal data generation -- **Test Types**: Unit, integration, negative, edge case, and performance tests -- **Smart Assertions**: Automatic schema validation and response verification - -### 2. Contract Testing Framework -- **Pact-like Implementation**: Provider-consumer contract verification -- **Contract Generation**: Auto-generate contracts from OpenAPI specs -- **Contract Registry**: Publish and verify contracts centrally -- **Schema Validation**: JSON schema-based contract validation - -### 3. Performance Benchmarking -- **Load Testing**: Normal and peak load conditions -- **Stress Testing**: System limits and breaking points -- **Spike Testing**: Sudden load increase scenarios -- **Endurance Testing**: Long-running performance validation -- **Real-time Metrics**: Response times, throughput, percentiles -- **Threshold Validation**: SLA-based performance validation - -### 4. Test Data Management -- **Realistic Mock Data**: Faker-based data generation -- **Schema-driven Generation**: Data based on API schemas -- **Multiple Strategies**: Random, realistic, minimal data options -- **Test Data Cleanup**: Automatic cleanup after test execution - -### 5. Comprehensive Reporting -- **Multiple Formats**: JSON, Markdown, HTML, JUnit XML -- **Detailed Metrics**: Performance trends, error analysis -- **Visual Reports**: Charts and graphs for performance data -- **Automated Recommendations**: AI-powered improvement suggestions - -## 🛠️ Usage Examples - -### Quick Start -```bash -# Run comprehensive tests -npm run test:comprehensive - -# Generate API tests from spec -npm run test:api-generation - -# Verify contracts -npm run test:contract-verification - -# Run performance tests -npm run test:performance-suite -``` - -### Programmatic Usage -```typescript -// Create test suite -const testSuite = { - name: 'api-tests', - testGeneration: { includeNegativeTests: true }, - contractTesting: { enabled: true }, - performanceTesting: { - enabled: true, - endpoints: [/* ... */], - thresholds: { maxResponseTime: 1000 } - } -}; - -await testingService.createTestSuite(testSuite); - -// Execute tests -const result = await testingService.executeTestSuite('api-tests'); -``` - -### API Endpoints -```bash -# Create test suite -POST /api/v1/testing/suites - -# Execute tests -POST /api/v1/testing/suites/{name}/execute - -# Get results -GET /api/v1/testing/executions - -# Health check -GET /api/v1/testing/health -``` - -## 📊 Test Types Supported - -### Automated Test Generation -- ✅ Unit Tests -- ✅ Integration Tests -- ✅ Negative Tests -- ✅ Edge Case Tests -- ✅ Performance Tests -- ✅ Schema Validation Tests - -### Contract Testing -- ✅ Contract Generation -- ✅ Contract Verification -- ✅ Contract Publishing -- ✅ Schema Validation -- ✅ Provider-Consumer Testing - -### Performance Testing -- ✅ Load Testing -- ✅ Stress Testing -- ✅ Spike Testing -- ✅ Endurance Testing -- ✅ Benchmark Comparison -- ✅ Threshold Validation - -## 🔧 Configuration - -### Environment Variables -```bash -API_BASE_URL=http://localhost:3000 -CONTRACT_REGISTRY_URL=http://localhost:8080 -DEFAULT_TIMEOUT=30000 -DEFAULT_CONCURRENCY=10 -DEFAULT_DURATION=60 -``` - -### Test Suite Configuration -```json -{ - "name": "api-tests", - "testGeneration": { - "includeNegativeTests": true, - "mockDataStrategy": "realistic" - }, - "contractTesting": { - "enabled": true, - "verificationOptions": { - "timeout": 30000, - "retries": 3 - } - }, - "performanceTesting": { - "enabled": true, - "endpoints": [/* ... */], - "thresholds": { - "maxResponseTime": 1000, - "minRequestsPerSecond": 100 - } - }, - "schedule": { - "enabled": true, - "cronExpression": "0 2 * * *" - } -} -``` - -## 📈 Integration with CI/CD - -### GitHub Actions -```yaml -- name: Run Comprehensive Tests - run: npm run test:comprehensive - -- name: Upload Test Reports - uses: actions/upload-artifact@v2 - with: - name: test-reports - path: test-reports/ -``` - -### Docker Integration -```dockerfile -# Run tests in Docker -RUN npm run test:comprehensive -COPY test-reports/ /app/test-reports/ -``` - -## 🎯 Benefits Achieved - -### 1. Automated Testing -- **Reduced Manual Effort**: Automatic test generation from API specs -- **Comprehensive Coverage**: Multiple test types automatically generated -- **Consistent Testing**: Standardized test patterns and assertions - -### 2. Quality Assurance -- **Contract Compliance**: Ensures API contracts are maintained -- **Performance Monitoring**: Continuous performance validation -- **Early Detection**: Issues caught before production deployment - -### 3. Developer Experience -- **Easy Setup**: Simple configuration and execution -- **Rich Reporting**: Detailed insights and recommendations -- **API Integration**: RESTful API for test management - -### 4. Operations Excellence -- **Scheduled Testing**: Automated test execution -- **Health Monitoring**: System health checks -- **Trend Analysis**: Performance tracking over time - -## 🚦 Getting Started - -### 1. Install Dependencies -```bash -npm install -``` - -### 2. Configure Environment -```bash -cp .env.example .env -# Edit .env with your configuration -``` - -### 3. Run Tests -```bash -# Quick health check -npm run test:health - -# Comprehensive test suite -npm run test:comprehensive - -# Specific test types -npm run test:api-generation -npm run test:contract-verification -npm run test:performance-suite -``` - -### 4. Review Results -```bash -# View generated reports -ls test-reports/ - -# Open comprehensive report -cat test-reports/comprehensive-report-*.md -``` - -## 📚 Documentation - -- **[Complete Documentation](docs/testing.md)**: Comprehensive guide -- **[API Reference](src/testing/testing.controller.ts)**: REST API endpoints -- **[Configuration Examples](test-suites/)**: Sample configurations - -## 🔮 Future Enhancements - -Planned improvements include: -- Visual test dashboards -- AI-powered test optimization -- Distributed testing support -- Real-time monitoring -- Advanced analytics - -## 🤝 Contributing - -1. Fork the repository -2. Create a feature branch -3. Add tests for new functionality -4. Submit a pull request - -## 📞 Support - -For questions or issues: -- Check the documentation in `docs/testing.md` -- Review generated test reports -- Consult the API documentation - ---- - -## ✅ Issue Resolution Status - -**Issue #240**: ✅ **COMPLETED** - -All required features have been implemented: -- ✅ Automated API test generation -- ✅ Contract testing framework -- ✅ Performance benchmarking -- ✅ Load testing automation -- ✅ Test data management -- ✅ Comprehensive documentation - -The implementation provides a robust, scalable, and comprehensive testing solution for the PropChain backend API. diff --git a/TYPE_SAFETY_PR.md b/TYPE_SAFETY_PR.md deleted file mode 100644 index c735ab1b..00000000 --- a/TYPE_SAFETY_PR.md +++ /dev/null @@ -1,162 +0,0 @@ -# Fix Excessive Use of 'any' Type - Implement Strict Type Safety - -## 🎯 **Objective** -Address the issue of 615+ instances of 'any' type reducing type safety in the PropChain-BackEnd codebase by implementing proper TypeScript types and strict type checking. - -## 📊 **Impact Summary** -- **Before**: 615+ instances of 'any' type -- **After**: ~250 remaining instances (60% reduction) -- **Type Safety**: Significantly improved with strict TypeScript configuration -- **Files Changed**: 9 files modified, 1 new file created - -## ✅ **Acceptance Criteria Met** - -### 1. Replace 'any' with proper TypeScript types ✅ -- **User Module**: Completely refactored with proper types - - `UserPreferences` interface for user settings - - `PrivacySettings` interface for privacy controls - - `TransactionMetadata` interface for activity tracking - - Proper typing for all DTOs and service methods - -- **API Layer**: Enhanced with generic types - - `HttpRequest` and `HttpResponse` for type-safe HTTP handling - - `WebSocketMessage` for WebSocket communications - - `GraphQLResponse` and related types with proper generics - -- **Validation System**: Type-safe validation - - Replaced `any` with `unknown` where appropriate - - Added proper generic constraints to validation rules - - Enhanced type safety in validation contexts - -### 2. Implement strict type checking ✅ -Updated `tsconfig.json` with comprehensive strict settings: -```json -{ - "strict": true, - "noImplicitAny": true, - "strictNullChecks": true, - "strictFunctionTypes": true, - "strictPropertyInitialization": true, - "noImplicitThis": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "exactOptionalPropertyTypes": true, - "noImplicitReturns": true, - "noUncheckedIndexedAccess": true, - "noImplicitOverride": true -} -``` - -### 3. Add type validation utilities ✅ -Created comprehensive `src/utils/type-validation.utils.ts` with: -- **Type Guards**: `isString()`, `isNumber()`, `isBoolean()`, `isDate()`, `isArray()`, `isObject()` -- **Runtime Validation**: `validateUserPreferences()`, `validatePrivacySettings()`, `validatePaginationOptions()` -- **Utility Functions**: `createPaginatedResult()`, `createApiResponse()`, type assertion utilities -- **Common Interfaces**: `BaseEntity`, `PaginationOptions`, `UserPreferences`, `PrivacySettings`, etc. - -## 🔧 **Technical Changes** - -### Files Modified -1. **`tsconfig.json`** - Enabled strict TypeScript checking -2. **`src/users/dto/create-user.dto.ts`** - Replaced `any` with proper types -3. **`src/users/dto/user-response.dto.ts`** - Added type-safe interfaces -4. **`src/users/user.controller.ts`** - Updated method signatures with proper types -5. **`src/users/user.service.ts`** - Complete type safety refactor -6. **`src/types/api.types.ts`** - Enhanced with generic types -7. **`src/types/validation.types.ts`** - Replaced `any` with `unknown` and proper generics -8. **`src/types/index.ts`** - Updated exports to include new types - -### Files Created -1. **`src/utils/type-validation.utils.ts`** - Comprehensive type validation utilities - -## 📈 **Benefits Achieved** - -### Type Safety Improvements -- **Compile-time Safety**: Strict checking prevents type-related runtime errors -- **Developer Experience**: Better IDE support with autocomplete and error detection -- **Code Maintainability**: Self-documenting code with explicit types -- **Refactoring Safety**: Type system prevents breaking changes during refactoring - -### Runtime Validation -- **Input Validation**: Type-safe validation for user inputs -- **API Responses**: Consistent and typed API responses -- **Error Handling**: Better error messages with type context - -## 🔍 **Remaining 'any' Types (~250 instances)** - -The remaining `any` types are intentionally left in place for valid reasons: - -### Security Middleware (~50 instances) -- Express.js request/response objects (framework limitation) -- Middleware function signatures (required by Express) -- Security scanning utilities (dynamic object inspection) - -### Prisma Types (~30 instances) -- Database field types awaiting schema generation -- Decimal/JSON types (will be resolved when Prisma client is generated) -- Transitional types during database migrations - -### Test Files (~100 instances) -- Test utilities and mocks (intentionally flexible) -- E2E test helpers (dynamic data generation) -- Integration test setup (framework requirements) - -### Legacy Code (~70 instances) -- Complex query builders requiring further refactoring -- Third-party integrations with loose typing -- Performance-critical code needing optimization - -## 🧪 **Testing Strategy** - -### Type Checking -- All changes pass strict TypeScript compilation -- No implicit any errors remaining in core application code -- Proper type inference maintained throughout - -### Runtime Validation -- Added validation utilities for critical user inputs -- Type guards ensure runtime type safety -- Error handling provides meaningful messages - -### Backward Compatibility -- All existing API endpoints maintain compatibility -- Database schema unchanged -- No breaking changes to public interfaces - -## 🚀 **Deployment Considerations** - -### Build Process -- TypeScript compilation will now catch more errors at build time -- Stricter checking may reveal previously hidden issues -- Recommend thorough testing in staging environment - -### Performance Impact -- Minimal performance overhead from type checking (compile-time only) -- Runtime validation utilities are lightweight and optional -- Improved developer productivity outweighs minimal costs - -## 📋 **Review Checklist** - -- [ ] TypeScript compilation succeeds with strict settings -- [ ] All user-related functionality works correctly -- [ ] API responses maintain expected structure -- [ ] Validation utilities work as expected -- [ ] No regression in existing functionality -- [ ] Error messages are clear and helpful -- [ ] Documentation is updated where necessary - -## 🔮 **Future Improvements** - -### Phase 2 (Recommended) -- Address remaining security middleware types with Express-specific types -- Generate Prisma client to resolve database type issues -- Create specific test utilities to reduce test file 'any' usage - -### Phase 3 (Long-term) -- Refactor legacy code with proper architectural patterns -- Implement domain-driven design with strongly-typed entities -- Add comprehensive integration test coverage - ---- - -**This PR represents a significant step toward type safety while maintaining system stability and developer productivity.** diff --git a/admin.controller.ts b/admin.controller.ts deleted file mode 100644 index 7fd6d9ca..00000000 --- a/admin.controller.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @fileoverview Controller for admin-only endpoints. - * @issue #206 - */ - -import { Controller, Get, Query, UseGuards } from '@nestjs/common'; -import { AdminService } from './admin.service'; -import { AdminGuard } from './guards/admin.guard'; -import { - AdminDashboardQueryDto, - AdminDashboardResponseDto, -} from './dto/dashboard.dto'; -import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; - -@ApiTags('Admin') -@Controller('admin') -@UseGuards(AdminGuard) -export class AdminController { - constructor(private readonly adminService: AdminService) {} - - @Get('dashboard') - @ApiOperation({ summary: 'Get platform-wide analytics for the admin dashboard' }) - @ApiResponse({ status: 200, description: 'Successfully retrieved dashboard data.', type: AdminDashboardResponseDto }) - @ApiResponse({ status: 403, description: 'Forbidden. User is not an admin.' }) - getDashboardAnalytics( - @Query() query: AdminDashboardQueryDto, - ): Promise { - return this.adminService.getDashboardAnalytics(query); - } -} \ No newline at end of file diff --git a/admin.guard.ts b/admin.guard.ts deleted file mode 100644 index 7dbc1a20..00000000 --- a/admin.guard.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @fileoverview A guard to protect routes for admin users only. - * @issue #206 - */ - -import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; -import { Observable } from 'rxjs'; - -@Injectable() -export class AdminGuard implements CanActivate { - canActivate( - context: ExecutionContext, - ): boolean | Promise | Observable { - const request = context.switchToHttp().getRequest(); - const user = request.user; - - // In a real app, this would be a more robust check (e.g., user.roles.includes('admin')) - return user && user.role === 'admin'; - } -} \ No newline at end of file diff --git a/admin.module.ts b/admin.module.ts deleted file mode 100644 index b51c0cbf..00000000 --- a/admin.module.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @fileoverview Module for admin-related features. - * @issue #206 - */ - -import { Module } from '@nestjs/common'; -import { AdminController } from './admin.controller'; -import { AdminService } from './admin.service'; -import { PrismaModule } from '../database/prisma/prisma.module'; - -@Module({ - imports: [PrismaModule], - controllers: [AdminController], - providers: [AdminService], -}) -export class AdminModule {} \ No newline at end of file diff --git a/admin.service.ts b/admin.service.ts deleted file mode 100644 index 89b208cb..00000000 --- a/admin.service.ts +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @fileoverview Service for admin-specific functionalities, like dashboard analytics. - * @issue #206 - */ - -import { Injectable } from '@nestjs/common'; -import { PrismaService } from '../database/prisma/prisma.service'; -import { - AdminDashboardQueryDto, - AdminDashboardResponseDto, -} from './dto/dashboard.dto'; - -@Injectable() -export class AdminService { - constructor(private readonly prisma: PrismaService) {} - - async getDashboardAnalytics( - query: AdminDashboardQueryDto, - ): Promise { - const { startDate, endDate } = query; - - const dateFilter = - startDate && endDate ? { gte: startDate, lte: endDate } : undefined; - - const [ - userCounts, - projectCounts, - donationStats, - feeStats, - recentActivity, - ] = await this.prisma.$transaction([ - // 1. Get user counts by role - this.prisma.user.groupBy({ - by: ['role'], - _count: { id: true }, - where: dateFilter ? { createdAt: dateFilter } : undefined, - }), - // 2. Get project counts by status - this.prisma.project.groupBy({ - by: ['status'], - _count: { id: true }, - where: dateFilter ? { createdAt: dateFilter } : undefined, - }), - // 3. Get total donation amount and count - this.prisma.donation.aggregate({ - _sum: { amount: true }, - _count: { id: true }, - where: dateFilter ? { createdAt: dateFilter } : undefined, - }), - // 4. Get total platform fees collected - this.prisma.platformFee.aggregate({ - _sum: { amount: true }, - where: dateFilter ? { createdAt: dateFilter } : undefined, - }), - // 5. Get recent platform activity - this.prisma.activityLog.findMany({ - take: 20, - orderBy: { createdAt: 'desc' }, - where: dateFilter ? { createdAt: dateFilter } : undefined, - }), - ]); - - // Format user stats - const usersByRole = userCounts.reduce((acc, item) => { - acc[item.role] = item._count.id; - return acc; - }, {}); - const totalUsers = userCounts.reduce((sum, item) => sum + item._count.id, 0); - - // Format project stats - const projectsByStatus = projectCounts.reduce((acc, item) => { - acc[item.status] = item._count.id; - return acc; - }, {}); - const totalProjects = projectCounts.reduce( - (sum, item) => sum + item._count.id, - 0, - ); - - return { - userStats: { - total: totalUsers, - byRole: usersByRole, - }, - projectStats: { - total: totalProjects, - byStatus: projectsByStatus, - }, - donationStats: { - totalAmount: donationStats._sum.amount || 0, - totalCount: donationStats._count.id || 0, - }, - platformFees: { - totalCollected: feeStats._sum.amount || 0, - }, - recentActivity, - query: { - startDate, - endDate, - }, - }; - } -} \ No newline at end of file diff --git a/benchmarks/chains/README.md b/benchmarks/chains/README.md deleted file mode 100644 index 1f2ed4bb..00000000 --- a/benchmarks/chains/README.md +++ /dev/null @@ -1,351 +0,0 @@ -# Middleware Stack Performance Benchmarks - -Comprehensive performance benchmarking suite for measuring middleware stack overhead in NestJS applications. - -## 📊 Overview - -This benchmarking system measures the **cumulative cost** of stacking multiple middleware - not just individual middleware performance. Real applications stack multiple middleware, and the interaction cost can be non-obvious due to: - -- Shared state contention (Redis connections, memory) -- Blocking calls in synchronous middleware -- Memory pressure affecting GC frequency -- Non-linear scaling effects - -## 🎯 What We Measure - -### Three Stack Profiles - -1. **Minimal Stack** (Logger + Error Handler) - - Baseline production configuration - - ~0.5ms average response time - - ~2000 RPS throughput - -2. **Auth Stack** (JWT + Rate Limit + Logger) - - Authentication-focused endpoints - - ~1.7ms average response time (+240% over baseline) - - ~588 RPS throughput - -3. **Full Stack** (All Production Middleware) - - Complete security and performance stack - - ~4.0ms average response time (+700% over baseline) - - ~250 RPS throughput - -## 🚀 Quick Start - -### Run Benchmarks - -```bash -# Default configuration (1000 iterations, 10 concurrency) -npx ts-node benchmarks/chains/run-benchmarks.ts - -# Custom configuration -npx ts-node benchmarks/chains/run-benchmarks.ts \ - --iterations=5000 \ - --concurrency=20 \ - --output=custom-report.md -``` - -### View Results - -Results are saved to `docs/PERFORMANCE.md` by default, or your specified output path. - -## 📁 Directory Structure - -``` -benchmarks/chains/ -├── types/ -│ └── benchmark-types.ts # Type definitions -├── utils/ -│ └── performance-measurer.ts # High-precision measurement utilities -├── stacks/ -│ ├── minimal.stack.ts # Minimal stack configuration -│ ├── auth.stack.ts # Auth stack configuration -│ └── full.stack.ts # Full stack configuration -├── benchmark-runner.ts # Benchmark execution engine -├── benchmark-reporter.ts # Report generation -├── run-benchmarks.ts # Main entry point -└── index.ts # Module exports -``` - -## 🔧 Configuration Options - -### Command Line Arguments - -| Argument | Description | Default | -|----------|-------------|---------| -| `--iterations=` | Number of benchmark iterations | 1000 | -| `--concurrency=` | Number of concurrent requests | 10 | -| `--output=` | Output file path for report | `docs/PERFORMANCE.md` | - -### Programmatic Configuration - -```typescript -import { DEFAULT_BENCHMARK_CONFIG } from './types/benchmark-types'; - -const config = { - ...DEFAULT_BENCHMARK_CONFIG, - warmupIterations: 200, // Warmup requests - benchmarkIterations: 2000, // Actual benchmark requests - concurrency: 15, // Parallel requests - timeoutMs: 30000, // Per-request timeout - profileEnabled: true, // Enable detailed profiling -}; -``` - -## 📈 Metrics Collected - -### Response Time Metrics -- **Min**: Fastest request -- **Max**: Slowest request -- **Average**: Mean response time -- **Median**: 50th percentile -- **P95**: 95th percentile (excludes worst 5%) -- **P99**: 99th percentile (excludes worst 1%) -- **Standard Deviation**: Variability measure - -### Throughput Metrics -- **RPS**: Requests per second -- **Total Requests**: Number of requests processed -- **Failed Requests**: Number of timeouts/errors -- **Error Rate**: Percentage of failed requests - -### Resource Metrics -- **Memory Used**: Bytes allocated per request -- **CPU Time**: Milliseconds of CPU time - -## 📊 Sample Output - -``` -🚀 Starting Middleware Stack Performance Benchmarks - -Configuration: - Iterations: 1000 - Concurrency: 10 - Output: docs/PERFORMANCE.md - -📊 Running benchmark: Minimal Stack - Description: Bare minimum production middleware (Logger + Error Handler) - Components: LoggingMiddleware, AllExceptionsFilter - Iterations: 1000 - Concurrency: 10 - -🔥 Warming up... -⚡ Running benchmarks... - -📈 Results Summary: - Min: 0.42 ms - Max: 1.23 ms - Avg: 0.51 ms - Median: 0.48 ms - P95: 0.78 ms - P99: 1.15 ms - Std Dev: 0.12 ms - RPS: 1960.78 - Error Rate: 0.00% - -[... repeats for Auth and Full stacks ...] - -📊 Generating comprehensive report... -📄 Report saved to: docs/PERFORMANCE.md - -================================================================================ -EXECUTIVE SUMMARY -================================================================================ - -Fastest Stack: Minimal Stack -Slowest Stack: Full Stack -Best RPS: 1960.78 -Worst RPS: 250.00 - -📋 Top Recommendations: - 1. Optimize SecurityMiddleware middleware - 2. Review Full Stack Middleware Necessity - 3. Consider Async Processing - -✅ Benchmarks completed successfully! -``` - -## 🎯 Key Findings - -### Non-Linear Scaling - -The Full Stack costs **more than the sum of its parts**: - -- Individual components sum: ~3.5ms -- Actual measured overhead: ~4.0ms -- **Disproportionate overhead: ~14%** - -This indicates: -1. Shared state contention (Redis/cache access) -2. Blocking calls in async code paths -3. Memory pressure increasing GC frequency - -### Component Overhead Breakdown - -| Component | Overhead (ms) | % of Total | Bottleneck? | -|-----------|--------------|------------|-------------| -| SecurityMiddleware | 1.2 | 30% | ⚠️ Yes | -| CompressionMiddleware | 0.8 | 20% | ⚠️ Yes | -| JwtAuthGuard | 0.8 | 20% | ⚠️ Yes | -| AdvancedRateLimitGuard | 0.5 | 12.5% | ✅ No | -| HeaderValidationMiddleware | 0.4 | 10% | ✅ No | -| ApiVersionMiddleware | 0.2 | 5% | ✅ No | -| LoggingMiddleware | 0.1 | 2.5% | ✅ No | - -## 💡 Optimization Recommendations - -### High Priority - -1. **Optimize Security Middleware** (30-40% improvement potential) - - Cache IP reputation checks (TTL: 5 min) - - Async DDoS detection with background processing - - Circuit breaker for external services - -2. **Lazy-Load Heavy Middleware** (50% for non-sensitive endpoints) - - Apply compression only to responses >1KB - - Skip DDoS checks for authenticated users - - Conditional header validation - -3. **Async Rate Limiting** (20-30% improvement) - - Redis pipelining - - Sliding window algorithm - - Local caching with eventual consistency - -### Medium Priority - -4. **Optimize JWT Validation** (15-20% improvement) - - Cache decoded tokens (short TTL) - - Use HS256 for internal services - - Token introspection caching - -5. **Reduce Logging Overhead** (5-10% improvement) - - Async logging with buffered writes - - Sampling for high-volume endpoints - - Strategic log level usage - -## 🔬 Methodology - -### Benchmark Process - -1. **Warmup Phase**: 100 iterations to stabilize performance -2. **Benchmark Phase**: 1000+ iterations with controlled concurrency -3. **Measurement**: High-resolution timing (hrtime) -4. **Statistics**: Percentiles, standard deviation, RPS calculation -5. **Comparison**: Baseline vs each stack, component attribution - -### Statistical Rigor - -- **Percentiles**: Accurate P95/P99 calculations -- **Outlier Handling**: Requests >3σ excluded from analysis -- **Confidence**: 95% confidence intervals -- **Repeatability**: Multiple runs averaged - -### Environment Capture - -Each benchmark records: -- Node.js version -- Platform and CPU info -- Memory availability -- NestJS version -- Timestamp - -## 🧪 Using in Your Tests - -### Import Benchmark Utilities - -```typescript -import { BenchmarkRunner, BenchmarkReporter } from './benchmarks/chains'; -import { MinimalStackModule } from './benchmarks/chains/stacks/minimal.stack'; - -// Create test app -const app = await NestFactory.create(MinimalStackModule); -await app.init(); - -// Run benchmark -const runner = new BenchmarkRunner(); -const result = await runner.runBenchmark( - app, - 'My Custom Stack', - 'Description here', - ['Middleware1', 'Middleware2'], - '/api/test-endpoint' -); - -// Generate report -const reporter = new BenchmarkReporter(); -const report = reporter.generateReport([result], DEFAULT_BENCHMARK_CONFIG); -``` - -## 📊 Continuous Monitoring - -### CI/CD Integration - -Add to your GitHub Actions workflow: - -```yaml -- name: Run Middleware Benchmarks - run: npx ts-node benchmarks/chains/run-benchmarks.ts - -- name: Check Performance Budget - run: node scripts/check-performance-budget.js -``` - -### Performance Budget - -Set thresholds to prevent regressions: - -```json -{ - "budget": { - "minimalStack": { "avgMs": 1.0, "rps": 1000 }, - "authStack": { "avgMs": 3.0, "rps": 500 }, - "fullStack": { "avgMs": 8.0, "rps": 200 } - } -} -``` - -## 🐛 Troubleshooting - -### Common Issues - -**Issue**: Benchmarks show high variability -**Solution**: Increase warmup iterations, check for background processes - -**Issue**: RPS seems too low -**Solution**: Check if running in production mode, verify no debug logging - -**Issue**: Memory errors during benchmarks -**Solution**: Reduce concurrency, increase available memory - -## 📚 Related Documentation - -- [Performance Analysis Report](../../docs/PERFORMANCE.md) - Detailed findings and recommendations -- [API Security Guide](../../docs/API_SECURITY_GUIDE.md) - Security middleware details -- [Load Testing](../../docs/LOAD_TESTING.md) - Application-level load testing - -## 🤝 Contributing - -### Adding New Stacks - -1. Create new stack file in `stacks/` directory -2. Define module with middleware configuration -3. Add stack config constant -4. Update `run-benchmarks.ts` to include new stack -5. Run benchmarks and update documentation - -### Improving Accuracy - -- Use high-resolution timers (`process.hrtime.bigint()`) -- Account for GC pauses -- Run multiple iterations and average results -- Control environmental factors (temperature, background processes) - -## 📝 License - -MIT - PropChain Project - ---- - -**Maintained by**: PropChain Performance Team -**Last Updated**: March 27, 2026 -**Version**: 1.0.0 diff --git a/benchmarks/chains/benchmark-reporter.ts b/benchmarks/chains/benchmark-reporter.ts deleted file mode 100644 index 70199f9a..00000000 --- a/benchmarks/chains/benchmark-reporter.ts +++ /dev/null @@ -1,377 +0,0 @@ -import { BenchmarkReport, BenchmarkResult, ComparativeAnalysis, ComponentOverhead, StackRanking, Recommendation } from '../types/benchmark-types'; -import * as fs from 'fs'; -import * as path from 'path'; - -/** - * Generates comprehensive benchmark reports and documentation - */ -export class BenchmarkReporter { - /** - * Generate complete benchmark report - */ - generateReport( - results: BenchmarkResult[], - config: import('../types/benchmark-types').BenchmarkConfig, - ): BenchmarkReport { - const environment = this.getEnvironmentInfo(); - - // Find baseline (no middleware) for comparisons - const baseline = results.find(r => r.middlewareComponents.length === 0); - - // Add baseline comparisons to each result - const resultsWithComparison = baseline - ? results.map(result => ({ - ...result, - baselineComparison: this.compareWithBaseline(result, baseline), - })) - : results; - - // Generate comparative analysis - const comparativeAnalysis = this.generateComparativeAnalysis(resultsWithComparison); - - // Generate recommendations - const recommendations = this.generateRecommendations(resultsWithComparison, comparativeAnalysis); - - return { - generatedAt: new Date(), - environment, - config, - stackResults: this.indexResultsByStackName(resultsWithComparison), - comparativeAnalysis, - recommendations, - }; - } - - /** - * Compare result with baseline - */ - private compareWithBaseline( - result: BenchmarkResult, - baseline: BenchmarkResult, - ): import('../types/benchmark-types').BaselineComparison { - const absoluteOverheadMs = result.stats.avgMs - baseline.stats.avgMs; - const relativeOverheadPercent = (absoluteOverheadMs / baseline.stats.avgMs) * 100; - const rpsDifference = result.stats.rps - baseline.stats.rps; - const isSignificantlySlower = relativeOverheadPercent > 10 || absoluteOverheadMs > 5; - - return { - baselineName: baseline.stackName, - absoluteOverheadMs, - relativeOverheadPercent, - rpsDifference, - isSignificantlySlower, - }; - } - - /** - * Generate comparative analysis - */ - private generateComparativeAnalysis(results: BenchmarkResult[]): ComparativeAnalysis { - const sorted = [...results].sort((a, b) => a.stats.avgMs - b.stats.avgMs); - - const fastest = sorted[0]; - const slowest = sorted[sorted.length - 1]; - - const ranking: StackRanking[] = sorted.map((result, index) => ({ - rank: index + 1, - stackName: result.stackName, - avgResponseTimeMs: result.stats.avgMs, - rps: result.stats.rps, - score: this.calculatePerformanceScore(result), - })); - - const componentOverhead = this.analyzeComponentOverhead(results); - - return { - fastestStack: fastest.stackName, - slowestStack: slowest.stackName, - bestRps: fastest.stats.rps, - worstRps: slowest.stats.rps, - componentOverhead, - ranking, - }; - } - - /** - * Analyze overhead contributed by each middleware component - */ - private analyzeComponentOverhead(results: BenchmarkResult[]): ComponentOverhead[] { - const baseline = results.find(r => r.middlewareComponents.length === 0); - if (!baseline) return []; - - const baseAvg = baseline.stats.avgMs; - const components = new Map(); - - // Collect overhead data for each component - results.forEach(result => { - const totalOverhead = result.stats.avgMs - baseAvg; - result.middlewareComponents.forEach(component => { - if (!components.has(component)) { - components.set(component, []); - } - components.get(component)!.push(totalOverhead / result.middlewareComponents.length); - }); - }); - - // Calculate average overhead per component - const overheadList: ComponentOverhead[] = Array.from(components.entries()).map(([component, overheads]) => { - const avgOverhead = overheads.reduce((a, b) => a + b, 0) / overheads.length; - const totalOverhead = results.reduce((sum, r) => sum + (r.stats.avgMs - baseAvg), 0); - const overheadPercent = (avgOverhead / totalOverhead) * 100; - const isBottleneck = avgOverhead > 2 || overheadPercent > 20; - - return { - component, - estimatedOverheadMs: avgOverhead, - overheadPercent, - isBottleneck, - }; - }); - - return overheadList.sort((a, b) => b.estimatedOverheadMs - a.estimatedOverheadMs); - } - - /** - * Generate performance optimization recommendations - */ - private generateRecommendations( - results: BenchmarkResult[], - analysis: ComparativeAnalysis, - ): Recommendation[] { - const recommendations: Recommendation[] = []; - - // Check for bottlenecks - analysis.componentOverhead - .filter(c => c.isBottleneck) - .forEach(component => { - recommendations.push({ - priority: 1, - category: 'performance', - title: `Optimize ${component.component} middleware`, - description: `This component contributes ${component.overheadPercent.toFixed(1)}% of total overhead (${component.estimatedOverheadMs.toFixed(2)}ms). Consider optimizing or caching.`, - affectedComponents: [component.component], - expectedImprovement: `${(component.estimatedOverheadMs * 0.5).toFixed(2)}ms reduction possible`, - complexity: 'medium', - }); - }); - - // Check for disproportionate overhead in full stack - const fullStack = results.find(r => r.stackName.includes('Full')); - const minimalStack = results.find(r => r.stackName.includes('Minimal')); - - if (fullStack && minimalStack) { - const overheadRatio = fullStack.stats.avgMs / minimalStack.stats.avgMs; - - if (overheadRatio > 3) { - recommendations.push({ - priority: 2, - category: 'scalability', - title: 'Review Full Stack Middleware Necessity', - description: `Full stack is ${overheadRatio.toFixed(1)}x slower than minimal stack. Consider removing non-essential middleware or lazy-loading.`, - affectedComponents: fullStack.middlewareComponents, - expectedImprovement: `${((overheadRatio - 1) * 100).toFixed(0)}% performance improvement potential`, - complexity: 'high', - }); - } - } - - // General recommendations based on findings - if (analysis.worstRps < 100) { - recommendations.push({ - priority: 3, - category: 'performance', - title: 'Consider Async Processing', - description: 'Overall throughput is below 100 RPS. Consider moving heavy middleware operations to background jobs.', - affectedComponents: ['all'], - expectedImprovement: '2-5x throughput increase', - complexity: 'high', - }); - } - - return recommendations.sort((a, b) => a.priority - b.priority); - } - - /** - * Calculate performance score (normalized 0-100) - */ - private calculatePerformanceScore(result: BenchmarkResult): number { - const rpsWeight = 0.6; - const latencyWeight = 0.4; - - const rpsScore = Math.min(100, result.stats.rps); - const latencyScore = Math.max(0, 100 - result.stats.avgMs * 10); - - return rpsScore * rpsWeight + latencyScore * latencyWeight; - } - - /** - * Get environment information - */ - private getEnvironmentInfo(): import('../types/benchmark-types').EnvironmentInfo { - return { - nodeVersion: process.version, - platform: process.platform, - cpuModel: require('os').cpus()[0].model, - cpuCores: require('os').cpus().length, - totalMemoryGB: require('os').totalmem() / (1024 ** 3), - nestJsVersion: this.getNestJsVersion(), - }; - } - - /** - * Get NestJS version from package.json - */ - private getNestJsVersion(): string { - try { - const packageJson = JSON.parse( - fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8'), - ); - return packageJson.dependencies['@nestjs/common'] || 'unknown'; - } catch { - return 'unknown'; - } - } - - /** - * Index results by stack name - */ - private indexResultsByStackName(results: BenchmarkResult[]): Record { - return results.reduce((acc, result) => { - acc[result.stackName] = result; - return acc; - }, {} as Record); - } - - /** - * Save report to markdown file - */ - async saveToMarkdown(report: BenchmarkReport, filePath: string): Promise { - const md = this.generateMarkdown(report); - await fs.promises.writeFile(filePath, md, 'utf-8'); - console.log(`\n📄 Report saved to: ${filePath}`); - } - - /** - * Generate markdown documentation - */ - private generateMarkdown(report: BenchmarkReport): string { - const lines: string[] = []; - - lines.push('# Middleware Stack Performance Analysis'); - lines.push(''); - lines.push(`Generated: ${report.generatedAt.toISOString()}`); - lines.push(''); - lines.push('## Executive Summary'); - lines.push(''); - lines.push(`- **Fastest Stack**: ${report.comparativeAnalysis.fastestStack}`); - lines.push(`- **Slowest Stack**: ${report.comparativeAnalysis.slowestStack}`); - lines.push(`- **Best RPS**: ${report.comparativeAnalysis.bestRps.toFixed(2)}`); - lines.push(`- **Worst RPS**: ${report.comparativeAnalysis.worstRps.toFixed(2)}`); - lines.push(''); - - lines.push('## Environment'); - lines.push(''); - lines.push(`- Node.js: ${report.environment.nodeVersion}`); - lines.push(`- Platform: ${report.environment.platform}`); - lines.push(`- CPU: ${report.environment.cpuModel}`); - lines.push(`- Cores: ${report.environment.cpuCores}`); - lines.push(`- Memory: ${report.environment.totalMemoryGB.toFixed(2)} GB`); - lines.push(`- NestJS: ${report.environment.nestJsVersion}`); - lines.push(''); - - lines.push('## Stack Comparison'); - lines.push(''); - lines.push('| Stack | Avg (ms) | P95 (ms) | P99 (ms) | RPS | Error Rate |'); - lines.push('|-------|----------|----------|----------|-----|------------|'); - - Object.values(report.stackResults).forEach(result => { - lines.push( - `| ${result.stackName} | ${result.stats.avgMs.toFixed(2)} | ${result.stats.p95Ms.toFixed(2)} | ${result.stats.p99Ms.toFixed(2)} | ${result.stats.rps.toFixed(2)} | ${result.stats.errorRatePercent.toFixed(2)}% |` - ); - }); - lines.push(''); - - lines.push('## Baseline Comparison'); - lines.push(''); - lines.push('| Stack | Overhead (ms) | Overhead (%) | Significantly Slower |'); - lines.push('|-------|---------------|--------------|----------------------|'); - - Object.values(report.stackResults).forEach(result => { - if (result.baselineComparison) { - const bc = result.baselineComparison; - lines.push( - `| ${result.stackName} | ${bc.absoluteOverheadMs.toFixed(2)} | ${bc.relativeOverheadPercent.toFixed(2)}% | ${bc.isSignificantlySlower ? 'Yes' : 'No'} |` - ); - } - }); - lines.push(''); - - lines.push('## Component Overhead Analysis'); - lines.push(''); - lines.push('| Component | Overhead (ms) | % of Total | Bottleneck |'); - lines.push('|-----------|---------------|------------|------------|'); - - report.comparativeAnalysis.componentOverhead.forEach(comp => { - lines.push( - `| ${comp.component} | ${comp.estimatedOverheadMs.toFixed(2)} | ${comp.overheadPercent.toFixed(1)}% | ${comp.isBottleneck ? '⚠️' : '✅'} |` - ); - }); - lines.push(''); - - lines.push('## Performance Ranking'); - lines.push(''); - lines.push('| Rank | Stack | Score | Avg Response Time | RPS |'); - lines.push('|------|-------|-------|---------------------|-----|'); - - report.comparativeAnalysis.ranking.forEach(rank => { - lines.push( - `| ${rank.rank} | ${rank.stackName} | ${rank.score.toFixed(1)} | ${rank.avgResponseTimeMs.toFixed(2)} ms | ${rank.rps.toFixed(2)} |` - ); - }); - lines.push(''); - - lines.push('## Recommendations'); - lines.push(''); - - report.recommendations.forEach((rec, index) => { - lines.push(`### ${index + 1}. ${rec.title}`); - lines.push(''); - lines.push(`**Priority**: ${rec.priority}/5 `); - lines.push(`**Category**: ${rec.category} `); - lines.push(`**Complexity**: ${rec.complexity} `); - lines.push(''); - lines.push(rec.description); - lines.push(''); - lines.push(`**Affected Components**: ${rec.affectedComponents.join(', ')}`); - lines.push(''); - lines.push(`**Expected Improvement**: ${rec.expectedImprovement}`); - lines.push(''); - }); - - lines.push('## Detailed Results'); - lines.push(''); - - Object.values(report.stackResults).forEach(result => { - lines.push(`### ${result.stackName}`); - lines.push(''); - lines.push(`**Description**: ${result.stackDescription}`); - lines.push(''); - lines.push(`**Components**: ${result.middlewareComponents.join(', ')}`); - lines.push(''); - lines.push('#### Metrics'); - lines.push(''); - lines.push('- Min: ' + result.stats.minMs.toFixed(2) + ' ms'); - lines.push('- Max: ' + result.stats.maxMs.toFixed(2) + ' ms'); - lines.push('- Average: ' + result.stats.avgMs.toFixed(2) + ' ms'); - lines.push('- Median: ' + result.stats.medianMs.toFixed(2) + ' ms'); - lines.push('- P95: ' + result.stats.p95Ms.toFixed(2) + ' ms'); - lines.push('- P99: ' + result.stats.p99Ms.toFixed(2) + ' ms'); - lines.push('- Std Dev: ' + result.stats.stdDevMs.toFixed(2) + ' ms'); - lines.push('- RPS: ' + result.stats.rps.toFixed(2)); - lines.push('- Error Rate: ' + result.stats.errorRatePercent.toFixed(2) + '%'); - lines.push(''); - }); - - return lines.join('\n'); - } -} diff --git a/benchmarks/chains/benchmark-runner.ts b/benchmarks/chains/benchmark-runner.ts deleted file mode 100644 index d0ea1ab0..00000000 --- a/benchmarks/chains/benchmark-runner.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { INestApplication } from '@nestjs/common'; -import request from 'supertest'; -import { PerformanceMeasurer } from '../utils/performance-measurer'; -import { - BenchmarkConfig, - BenchmarkResult, - DEFAULT_BENCHMARK_CONFIG, -} from '../types/benchmark-types'; - -/** - * Runs benchmarks for middleware stacks - */ -@Injectable() -export class BenchmarkRunner { - private readonly measurer = new PerformanceMeasurer(); - - /** - * Run benchmark for a specific middleware stack - */ - async runBenchmark( - app: INestApplication, - stackName: string, - stackDescription: string, - middlewareComponents: string[], - endpoint: string = '/api/v1/benchmark/test', - config: BenchmarkConfig = DEFAULT_BENCHMARK_CONFIG, - ): Promise { - console.log(`\n📊 Running benchmark: ${stackName}`); - console.log(` Description: ${stackDescription}`); - console.log(` Components: ${middlewareComponents.join(', ')}`); - console.log(` Iterations: ${config.benchmarkIterations}`); - console.log(` Concurrency: ${config.concurrency}`); - - // Warmup phase - console.log('\n🔥 Warming up...'); - await this.runWarmup(app, endpoint, config.warmupIterations); - - // Benchmark phase - console.log('⚡ Running benchmarks...'); - const metrics = await this.measurer.runIterations( - () => this.makeRequest(app, endpoint), - config.benchmarkIterations, - config.concurrency, - ); - - // Calculate statistics - const stats = this.measurer.calculateStats(metrics, config.benchmarkIterations); - - const result: BenchmarkResult = { - stackName, - stackDescription, - middlewareComponents, - stats, - individualMetrics: metrics, - config, - runTimestamp: new Date(), - }; - - // Print summary - this.printSummary(result); - - return result; - } - - /** - * Run warmup requests to stabilize performance - */ - private async runWarmup(app: INestApplication, endpoint: string, iterations: number): Promise { - for (let i = 0; i < iterations; i++) { - await this.makeRequest(app, endpoint); - } - } - - /** - * Make a single HTTP request through the middleware stack - */ - private async makeRequest(app: INestApplication, endpoint: string): Promise { - const httpServer = app.getHttpServer(); - - await request(httpServer) - .get(endpoint) - .set('Accept', 'application/json') - .set('User-Agent', 'BenchmarkRunner/1.0') - .expect(200); - } - - /** - * Print benchmark summary to console - */ - private printSummary(result: BenchmarkResult): void { - console.log('\n📈 Results Summary:'); - console.log(` Min: ${result.stats.minMs.toFixed(2)} ms`); - console.log(` Max: ${result.stats.maxMs.toFixed(2)} ms`); - console.log(` Avg: ${result.stats.avgMs.toFixed(2)} ms`); - console.log(` Median: ${result.stats.medianMs.toFixed(2)} ms`); - console.log(` P95: ${result.stats.p95Ms.toFixed(2)} ms`); - console.log(` P99: ${result.stats.p99Ms.toFixed(2)} ms`); - console.log(` Std Dev: ${result.stats.stdDevMs.toFixed(2)} ms`); - console.log(` RPS: ${result.stats.rps.toFixed(2)}`); - console.log(` Error Rate: ${result.stats.errorRatePercent.toFixed(2)}%`); - } - - /** - * Compare two benchmark results - */ - compareResults(baseline: BenchmarkResult, comparison: BenchmarkResult): import('../types/benchmark-types').BaselineComparison { - const absoluteOverheadMs = comparison.stats.avgMs - baseline.stats.avgMs; - const relativeOverheadPercent = (absoluteOverheadMs / baseline.stats.avgMs) * 100; - const rpsDifference = comparison.stats.rps - baseline.stats.rps; - - // Consider significantly slower if overhead > 10% or > 5ms - const isSignificantlySlower = relativeOverheadPercent > 10 || absoluteOverheadMs > 5; - - return { - baselineName: baseline.stackName, - absoluteOverheadMs, - relativeOverheadPercent, - rpsDifference, - isSignificantlySlower, - }; - } -} diff --git a/benchmarks/chains/index.ts b/benchmarks/chains/index.ts deleted file mode 100644 index 9b160f6e..00000000 --- a/benchmarks/chains/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Middleware Stack Performance Benchmarks - * - * This module provides comprehensive performance benchmarking for different - * middleware stack configurations to measure cumulative overhead and identify - * performance bottlenecks. - * - * @module benchmarks/chains - */ - -export * from './benchmark-runner'; -export * from './benchmark-reporter'; -export * from './types/benchmark-types'; diff --git a/benchmarks/chains/run-benchmarks.ts b/benchmarks/chains/run-benchmarks.ts deleted file mode 100644 index b3bca00c..00000000 --- a/benchmarks/chains/run-benchmarks.ts +++ /dev/null @@ -1,176 +0,0 @@ -#!/usr/bin/env ts-node - -/** - * Middleware Stack Performance Benchmark Runner - * - * This script runs comprehensive performance benchmarks for different middleware - * stack configurations and generates detailed reports. - * - * Usage: - * ts-node benchmarks/chains/run-benchmarks.ts - * - * Options: - * --iterations= Number of benchmark iterations (default: 1000) - * --concurrency= Number of concurrent requests (default: 10) - * --output= Output path for report (default: docs/PERFORMANCE.md) - */ - -import { NestFactory } from '@nestjs/core'; -import { Controller, Get, Module } from '@nestjs/common'; -import { BenchmarkRunner } from './benchmark-runner'; -import { BenchmarkReporter } from './benchmark-reporter'; -import { DEFAULT_BENCHMARK_CONFIG } from './types/benchmark-types'; -import { MINIMAL_STACK_CONFIG, MinimalStackModule } from './stacks/minimal.stack'; -import { AUTH_STACK_CONFIG, AuthStackModule } from './stacks/auth.stack'; -import { FULL_STACK_CONFIG, FullStackModule } from './stacks/full.stack'; - -/** - * Simple test controller for benchmarking - */ -@Controller('/api/v1/benchmark') -class TestController { - @Get('/test') - testEndpoint() { - return { success: true, timestamp: new Date().toISOString() }; - } -} - -/** - * Test module with minimal configuration - */ -@Module({ - imports: [], - controllers: [TestController], -}) -class TestModule {} - -/** - * Parse command line arguments - */ -function parseArgs(): { iterations: number; concurrency: number; output: string } { - const args = process.argv.slice(2); - const config = { - iterations: DEFAULT_BENCHMARK_CONFIG.benchmarkIterations, - concurrency: DEFAULT_BENCHMARK_CONFIG.concurrency, - output: 'docs/PERFORMANCE.md', - }; - - args.forEach(arg => { - const [key, value] = arg.split('='); - if (key === '--iterations') config.iterations = parseInt(value, 10); - if (key === '--concurrency') config.concurrency = parseInt(value, 10); - if (key === '--output') config.output = value; - }); - - return config; -} - -/** - * Main benchmark execution - */ -async function runBenchmarks() { - const args = parseArgs(); - - console.log('🚀 Starting Middleware Stack Performance Benchmarks\n'); - console.log(`Configuration:`); - console.log(` Iterations: ${args.iterations}`); - console.log(` Concurrency: ${args.concurrency}`); - console.log(` Output: ${args.output}\n`); - - // Create application instance - const app = await NestFactory.create(TestModule, { - bufferLogs: true, - logger: false, // Disable logging during benchmarks - }); - - // Initialize benchmark components - const runner = new BenchmarkRunner(); - const reporter = new BenchmarkReporter(); - - try { - await app.init(); - - const results = []; - - // Run Minimal Stack benchmark - const minimalResult = await runner.runBenchmark( - app, - MINIMAL_STACK_CONFIG.name, - MINIMAL_STACK_CONFIG.description, - MINIMAL_STACK_CONFIG.components, - '/api/v1/benchmark/test', - { - ...DEFAULT_BENCHMARK_CONFIG, - benchmarkIterations: args.iterations, - concurrency: args.concurrency, - }, - ); - results.push(minimalResult); - - // Run Auth Stack benchmark - const authResult = await runner.runBenchmark( - app, - AUTH_STACK_CONFIG.name, - AUTH_STACK_CONFIG.description, - AUTH_STACK_CONFIG.components, - '/api/v1/benchmark/test', - { - ...DEFAULT_BENCHMARK_CONFIG, - benchmarkIterations: args.iterations, - concurrency: args.concurrency, - }, - ); - results.push(authResult); - - // Run Full Stack benchmark - const fullResult = await runner.runBenchmark( - app, - FULL_STACK_CONFIG.name, - FULL_STACK_CONFIG.description, - FULL_STACK_CONFIG.components, - '/api/v1/benchmark/test', - { - ...DEFAULT_BENCHMARK_CONFIG, - benchmarkIterations: args.iterations, - concurrency: args.concurrency, - }, - ); - results.push(fullResult); - - // Generate report - console.log('\n📊 Generating comprehensive report...'); - const report = reporter.generateReport(results, { - ...DEFAULT_BENCHMARK_CONFIG, - benchmarkIterations: args.iterations, - concurrency: args.concurrency, - }); - - // Save to markdown - await reporter.saveToMarkdown(report, args.output); - - // Print executive summary - console.log('\n' + '='.repeat(80)); - console.log('EXECUTIVE SUMMARY'); - console.log('='.repeat(80)); - console.log(`\nFastest Stack: ${report.comparativeAnalysis.fastestStack}`); - console.log(`Slowest Stack: ${report.comparativeAnalysis.slowestStack}`); - console.log(`Best RPS: ${report.comparativeAnalysis.bestRps.toFixed(2)}`); - console.log(`Worst RPS: ${report.comparativeAnalysis.worstRps.toFixed(2)}`); - - console.log('\n📋 Top Recommendations:'); - report.recommendations.slice(0, 3).forEach((rec, i) => { - console.log(` ${i + 1}. ${rec.title}`); - }); - - console.log('\n✅ Benchmarks completed successfully!\n'); - - } catch (error) { - console.error('❌ Benchmark failed:', error); - process.exit(1); - } finally { - await app.close(); - } -} - -// Execute benchmarks -runBenchmarks().catch(console.error); diff --git a/benchmarks/chains/stacks/auth.stack.ts b/benchmarks/chains/stacks/auth.stack.ts deleted file mode 100644 index 77dbdab9..00000000 --- a/benchmarks/chains/stacks/auth.stack.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Module, MiddlewareConsumer, RequestMethod, INestModule } from '@nestjs/common'; -import { LoggingMiddleware } from '../../src/common/logging/logging.middleware'; -import { AllExceptionsFilter } from '../../src/common/filters/all-exceptions.filter'; -import { ConfigModule } from '@nestjs/config'; -import { LoggerService } from '../../src/common/logger/logger.service'; - -/** - * Auth Stack Module - * - * Includes authentication-focused middleware: - * - LoggingMiddleware: Request correlation and logging - * - AdvancedRateLimitGuard: Rate limiting for API protection - * - JWT Authentication: Token validation (simulated for benchmarks) - * - * This represents a typical authentication-heavy stack. - */ -@Module({ - imports: [ConfigModule], - providers: [LoggerService], - exports: [LoggerService], -}) -export class AuthStackModule implements INestModule { - configure(consumer: MiddlewareConsumer): void { - // Apply logging middleware to all routes - consumer.apply(LoggingMiddleware).forRoutes({ - path: '*', - method: RequestMethod.ALL, - }); - - // Note: Rate limiting is typically applied as a guard - // For benchmarking purposes, we include it conceptually - // Actual implementation would use AdvancedRateLimitGuard - } -} - -/** - * Auth Stack Configuration - */ -export const AUTH_STACK_CONFIG = { - name: 'Auth Stack', - description: 'Authentication-focused middleware (JWT + Rate Limit + Logger)', - components: ['LoggingMiddleware', 'AdvancedRateLimitGuard', 'JwtAuthGuard'], -}; diff --git a/benchmarks/chains/stacks/full.stack.ts b/benchmarks/chains/stacks/full.stack.ts deleted file mode 100644 index da68ac44..00000000 --- a/benchmarks/chains/stacks/full.stack.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { Module, MiddlewareConsumer, RequestMethod, INestModule } from '@nestjs/common'; -import { LoggingMiddleware } from '../../src/common/logging/logging.middleware'; -import { AllExceptionsFilter } from '../../src/common/filters/all-exceptions.filter'; -import { ConfigModule } from '@nestjs/config'; -import { LoggerService } from '../../src/common/logger/logger.service'; - -/** - * Full Stack Module - * - * Includes all production middleware: - * - LoggingMiddleware: Request correlation and logging - * - SecurityMiddleware: IP blocking, DDoS protection, security headers - * - AdvancedRateLimitGuard: Tiered rate limiting - * - HeaderValidationMiddleware: Header security validation - * - ApiVersionMiddleware: API versioning - * - CompressionMiddleware: Response compression - * - Helmet: Security headers - * - * This represents the complete production middleware stack. - */ -@Module({ - imports: [ConfigModule], - providers: [LoggerService], - exports: [LoggerService], -}) -export class FullStackModule implements INestModule { - configure(consumer: MiddlewareConsumer): void { - // Apply logging middleware to all routes - consumer.apply(LoggingMiddleware).forRoutes({ - path: '*', - method: RequestMethod.ALL, - }); - - // Note: In actual implementation, other middleware would be applied here - // For benchmark purposes, we're measuring the conceptual full stack - } -} - -/** - * Full Stack Configuration - */ -export const FULL_STACK_CONFIG = { - name: 'Full Stack', - description: 'Complete production middleware stack (all security & performance middleware)', - components: [ - 'LoggingMiddleware', - 'SecurityMiddleware', - 'AdvancedRateLimitGuard', - 'HeaderValidationMiddleware', - 'ApiVersionMiddleware', - 'CompressionMiddleware', - 'Helmet', - 'AllExceptionsFilter', - ], -}; diff --git a/benchmarks/chains/stacks/minimal.stack.ts b/benchmarks/chains/stacks/minimal.stack.ts deleted file mode 100644 index 88ec63d3..00000000 --- a/benchmarks/chains/stacks/minimal.stack.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Module, MiddlewareConsumer, RequestMethod, INestModule } from '@nestjs/common'; -import { LoggingMiddleware } from '../../src/common/logging/logging.middleware'; -import { AllExceptionsFilter } from '../../src/common/filters/all-exceptions.filter'; -import { ConfigModule } from '@nestjs/config'; -import { LoggerService } from '../../src/common/logger/logger.service'; - -/** - * Minimal Stack Module - * - * Includes only essential middleware: - * - LoggingMiddleware: Request correlation and logging - * - AllExceptionsFilter: Global error handling - * - * This represents the bare minimum production configuration. - */ -@Module({ - imports: [ConfigModule], - providers: [LoggerService], - exports: [LoggerService], -}) -export class MinimalStackModule implements INestModule { - configure(consumer: MiddlewareConsumer): void { - // Apply logging middleware to all routes - consumer.apply(LoggingMiddleware).forRoutes({ - path: '*', - method: RequestMethod.ALL, - }); - } -} - -/** - * Minimal Stack Configuration - */ -export const MINIMAL_STACK_CONFIG = { - name: 'Minimal Stack', - description: 'Bare minimum production middleware (Logger + Error Handler)', - components: ['LoggingMiddleware', 'AllExceptionsFilter'], -}; diff --git a/benchmarks/chains/types/benchmark-types.ts b/benchmarks/chains/types/benchmark-types.ts deleted file mode 100644 index 69c87039..00000000 --- a/benchmarks/chains/types/benchmark-types.ts +++ /dev/null @@ -1,210 +0,0 @@ -/** - * Benchmark result metrics for a single request - */ -export interface BenchmarkMetrics { - /** Total execution time in milliseconds */ - durationMs: number; - /** Memory used in bytes */ - memoryUsedBytes: number; - /** CPU time in milliseconds */ - cpuTimeMs: number; - /** Timestamp when measurement was taken */ - timestamp: Date; -} - -/** - * Aggregated statistics for benchmark results - */ -export interface BenchmarkStats { - /** Minimum execution time */ - minMs: number; - /** Maximum execution time */ - maxMs: number; - /** Average execution time */ - avgMs: number; - /** Median execution time */ - medianMs: number; - /** 95th percentile execution time */ - p95Ms: number; - /** 99th percentile execution time */ - p99Ms: number; - /** Standard deviation */ - stdDevMs: number; - /** Requests per second */ - rps: number; - /** Total requests made */ - totalRequests: number; - /** Failed requests */ - failedRequests: number; - /** Error rate percentage */ - errorRatePercent: number; -} - -/** - * Configuration for running benchmarks - */ -export interface BenchmarkConfig { - /** Number of warmup requests */ - warmupIterations: number; - /** Number of benchmark iterations */ - benchmarkIterations: number; - /** Number of concurrent requests */ - concurrency: number; - /** Timeout per request in milliseconds */ - timeoutMs: number; - /** Enable detailed profiling */ - profileEnabled: boolean; -} - -/** - * Result from a complete benchmark run - */ -export interface BenchmarkResult { - /** Name of the benchmark stack */ - stackName: string; - /** Stack configuration description */ - stackDescription: string; - /** Middleware components in the stack */ - middlewareComponents: string[]; - /** Statistical results */ - stats: BenchmarkStats; - /** Individual metrics for each iteration */ - individualMetrics: BenchmarkMetrics[]; - /** Configuration used for this benchmark */ - config: BenchmarkConfig; - /** Baseline comparison (if available) */ - baselineComparison?: BaselineComparison; - /** When the benchmark was run */ - runTimestamp: Date; -} - -/** - * Comparison against baseline - */ -export interface BaselineComparison { - /** Baseline stack name */ - baselineName: string; - /** Absolute overhead in milliseconds */ - absoluteOverheadMs: number; - /** Relative overhead percentage */ - relativeOverheadPercent: number; - /** RPS difference */ - rpsDifference: number; - /** Is this stack significantly slower? */ - isSignificantlySlower: boolean; -} - -/** - * Complete benchmark report with all stacks - */ -export interface BenchmarkReport { - /** When the report was generated */ - generatedAt: Date; - /** Environment information */ - environment: EnvironmentInfo; - /** Configuration used */ - config: BenchmarkConfig; - /** Results for each stack */ - stackResults: Record; - /** Comparative analysis */ - comparativeAnalysis: ComparativeAnalysis; - /** Recommendations based on findings */ - recommendations: Recommendation[]; -} - -/** - * Environment information for reproducibility - */ -export interface EnvironmentInfo { - /** Node.js version */ - nodeVersion: string; - /** Platform */ - platform: string; - /** CPU info */ - cpuModel: string; - /** CPU cores */ - cpuCores: number; - /** Total memory in GB */ - totalMemoryGB: number; - /** NestJS version */ - nestJsVersion: string; -} - -/** - * Comparative analysis between stacks - */ -export interface ComparativeAnalysis { - /** Fastest stack */ - fastestStack: string; - /** Slowest stack */ - slowestStack: string; - /** Best RPS */ - bestRps: number; - /** Worst RPS */ - worstRps: number; - /** Overhead breakdown by component */ - componentOverhead: ComponentOverhead[]; - /** Performance ranking */ - ranking: StackRanking[]; -} - -/** - * Overhead attributed to specific middleware components - */ -export interface ComponentOverhead { - /** Component name */ - component: string; - /** Estimated overhead in ms */ - estimatedOverheadMs: number; - /** Percentage of total overhead */ - overheadPercent: number; - /** Is this a bottleneck? */ - isBottleneck: boolean; -} - -/** - * Stack performance ranking - */ -export interface StackRanking { - /** Rank position (1 = best) */ - rank: number; - /** Stack name */ - stackName: string; - /** Average response time */ - avgResponseTimeMs: number; - /** Requests per second */ - rps: number; - /** Score (normalized performance metric) */ - score: number; -} - -/** - * Performance optimization recommendation - */ -export interface Recommendation { - /** Priority level (1-5, 1 = highest) */ - priority: number; - /** Category */ - category: 'performance' | 'security' | 'scalability'; - /** Title/summary */ - title: string; - /** Detailed description */ - description: string; - /** Affected middleware/components */ - affectedComponents: string[]; - /** Expected improvement */ - expectedImprovement: string; - /** Implementation complexity */ - complexity: 'low' | 'medium' | 'high'; -} - -/** - * Default benchmark configuration - */ -export const DEFAULT_BENCHMARK_CONFIG: BenchmarkConfig = { - warmupIterations: 100, - benchmarkIterations: 1000, - concurrency: 10, - timeoutMs: 30000, - profileEnabled: true, -}; diff --git a/benchmarks/chains/utils/performance-measurer.ts b/benchmarks/chains/utils/performance-measurer.ts deleted file mode 100644 index dd25a04d..00000000 --- a/benchmarks/chains/utils/performance-measurer.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { BenchmarkMetrics, BenchmarkConfig, DEFAULT_BENCHMARK_CONFIG } from '../types/benchmark-types'; - -/** - * High-precision performance measurement utilities - */ -export class PerformanceMeasurer { - private readonly hrtime = process.hrtime.bigint; - - /** - * Measure execution time of a function - */ - async measureExecution(fn: () => Promise): Promise<{ result: T; metrics: BenchmarkMetrics }> { - const startTime = this.hrtime(); - const startMemory = process.memoryUsage(); - const startCpuTime = process.cpuUsage(); - - let result: T; - try { - result = await fn(); - } finally { - const endTime = this.hrtime(); - const endMemory = process.memoryUsage(); - const endCpuTime = process.cpuUsage(); - - // Calculate duration in milliseconds - const durationMs = Number(endTime - startTime) / 1_000_000; - - // Calculate memory difference in bytes - const memoryUsedBytes = - (endMemory.heapUsed - startMemory.heapUsed) + - (endMemory.rss - startMemory.rss); - - // Calculate CPU time in milliseconds - const cpuTimeMs = - (endCpuTime.user - startCpuTime.user) / 1000 + - (endCpuTime.system - startCpuTime.system) / 1000; - - const metrics: BenchmarkMetrics = { - durationMs, - memoryUsedBytes, - cpuTimeMs, - timestamp: new Date(), - }; - - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return { result: result!, metrics }; - } - } - - /** - * Run multiple iterations and collect metrics - */ - async runIterations( - fn: () => Promise, - iterations: number, - concurrency: number = 1, - ): Promise { - const metrics: BenchmarkMetrics[] = []; - - if (concurrency === 1) { - // Sequential execution - for (let i = 0; i < iterations; i++) { - const { metrics: iterationMetrics } = await this.measureExecution(fn); - metrics.push(iterationMetrics); - } - } else { - // Concurrent execution - const batchSize = Math.ceil(iterations / concurrency); - - for (let batch = 0; batch < concurrency; batch++) { - const batchPromises = []; - - for (let i = 0; i < batchSize && batch * batchSize + i < iterations; i++) { - batchPromises.push(this.measureExecution(fn)); - } - - const batchResults = await Promise.all(batchPromises); - metrics.push(...batchResults.map(r => r.metrics)); - } - } - - return metrics; - } - - /** - * Calculate statistics from metrics - */ - calculateStats(metrics: BenchmarkMetrics[], totalRequests: number): import('../types/benchmark-types').BenchmarkStats { - const durations = metrics.map(m => m.durationMs).sort((a, b) => a - b); - - const minMs = Math.min(...durations); - const maxMs = Math.max(...durations); - const avgMs = durations.reduce((a, b) => a + b, 0) / durations.length; - const medianMs = this.percentile(durations, 50); - const p95Ms = this.percentile(durations, 95); - const p99Ms = this.percentile(durations, 99); - const stdDevMs = this.standardDeviation(durations); - - const totalDurationSec = durations.reduce((a, b) => a + b, 0) / 1000; - const rps = totalRequests / totalDurationSec; - - const failedRequests = metrics.filter(m => m.durationMs > DEFAULT_BENCHMARK_CONFIG.timeoutMs).length; - const errorRatePercent = (failedRequests / totalRequests) * 100; - - return { - minMs, - maxMs, - avgMs, - medianMs, - p95Ms, - p99Ms, - stdDevMs, - rps, - totalRequests, - failedRequests, - errorRatePercent, - }; - } - - private percentile(sortedData: number[], p: number): number { - const index = Math.ceil((p / 100) * sortedData.length) - 1; - return sortedData[Math.max(0, index)]; - } - - private standardDeviation(data: number[]): number { - const n = data.length; - const avg = data.reduce((a, b) => a + b, 0) / n; - const squareDiffs = data.map(value => Math.pow(value - avg, 2)); - const avgSquareDiff = squareDiffs.reduce((a, b) => a + b, 0) / n; - return Math.sqrt(avgSquareDiff); - } -} diff --git a/benchmarks/memory/README.md b/benchmarks/memory/README.md deleted file mode 100644 index a6307b48..00000000 --- a/benchmarks/memory/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# Memory Profiling Benchmarks - -This directory contains in-process middleware memory profiling tools for leak detection. - -## What It Captures - -- Heap snapshot before the stress run -- Heap snapshot after the stress run -- Summary JSON with RSS, heap, and external memory deltas -- 10k request stress runs by default - -## Available Scenarios - -- `baseline`: terminal handler only -- `header-validation`: logging + header validation -- `circuit-breaker`: circuit breaker middleware -- `combined`: logging + header validation + circuit breaker - -## Usage - -```bash -npm run bench:memory -npm run bench:memory -- --scenario=header-validation -npm run bench:memory -- --scenario=circuit-breaker --requests=10000 --concurrency=50 -``` - -## Output - -Each run writes to `benchmarks/memory/output/-/`: - -- `before.heapsnapshot` -- `after.heapsnapshot` -- `summary.json` - -Open the `.heapsnapshot` files in Chrome DevTools or Node heap analysis tooling to inspect retained objects. - -## Current Cleanup Targets - -- `StaticCacheMiddleware`: response monkey-patching and cache metadata retention risk -- `CircuitBreakerMiddleware`: response-end wrapping and long-lived breaker state -- `TimeoutMiddleware`: per-request timer lifecycle and rejection paths -- `HeaderValidationMiddleware`: sanitized header attachment on every request diff --git a/benchmarks/memory/heap-snapshot.ts b/benchmarks/memory/heap-snapshot.ts deleted file mode 100644 index c6498ff6..00000000 --- a/benchmarks/memory/heap-snapshot.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { writeFile } from 'fs/promises'; -import inspector from 'inspector'; - -export async function writeHeapSnapshot(outputPath: string): Promise { - const session = new inspector.Session(); - const chunks: string[] = []; - - session.connect(); - session.on('HeapProfiler.addHeapSnapshotChunk', event => { - chunks.push(event.params.chunk); - }); - - await new Promise((resolve, reject) => { - session.post('HeapProfiler.takeHeapSnapshot', undefined, error => { - if (error) { - reject(error); - return; - } - resolve(); - }); - }); - - session.disconnect(); - await writeFile(outputPath, chunks.join(''), 'utf8'); -} diff --git a/benchmarks/memory/run-memory-profile.ts b/benchmarks/memory/run-memory-profile.ts deleted file mode 100644 index aa38fc6a..00000000 --- a/benchmarks/memory/run-memory-profile.ts +++ /dev/null @@ -1,231 +0,0 @@ -#!/usr/bin/env ts-node - -import { mkdir, writeFile } from 'fs/promises'; -import { join } from 'path'; -import { createServer, IncomingMessage, ServerResponse } from 'http'; -import { URL } from 'url'; -import { writeHeapSnapshot } from './heap-snapshot'; -import { getScenario, MEMORY_PROFILE_SCENARIOS } from './scenarios'; - -interface MemoryProfileArgs { - scenario: string; - requests: number; - concurrency: number; - outputDir: string; -} - -interface MemorySnapshotSummary { - rssMb: number; - heapTotalMb: number; - heapUsedMb: number; - externalMb: number; -} - -function parseArgs(): MemoryProfileArgs { - const args = process.argv.slice(2); - const config: MemoryProfileArgs = { - scenario: 'combined', - requests: 10000, - concurrency: 50, - outputDir: 'benchmarks/memory/output', - }; - - for (const arg of args) { - const [key, value] = arg.split('='); - if (key === '--scenario' && value) config.scenario = value; - if (key === '--requests' && value) config.requests = parseInt(value, 10); - if (key === '--concurrency' && value) config.concurrency = parseInt(value, 10); - if (key === '--output-dir' && value) config.outputDir = value; - } - - return config; -} - -function toMemorySummary(): MemorySnapshotSummary { - const usage = process.memoryUsage(); - - return { - rssMb: Number((usage.rss / 1024 / 1024).toFixed(2)), - heapTotalMb: Number((usage.heapTotal / 1024 / 1024).toFixed(2)), - heapUsedMb: Number((usage.heapUsed / 1024 / 1024).toFixed(2)), - externalMb: Number((usage.external / 1024 / 1024).toFixed(2)), - }; -} - -function addExpressLikeHelpers(req: IncomingMessage, res: ServerResponse): void { - const parsedUrl = new URL(req.url || '/', 'http://127.0.0.1'); - (req as IncomingMessage & { path?: string; body?: Record }).path = parsedUrl.pathname; - (req as IncomingMessage & { body?: Record }).body = {}; - - const responseWithHelpers = res as ServerResponse & { - status: (code: number) => ServerResponse; - json: (payload: unknown) => ServerResponse; - }; - - responseWithHelpers.status = function status(code: number) { - this.statusCode = code; - return this; - }; - - responseWithHelpers.json = function json(payload: unknown) { - this.setHeader('content-type', 'application/json'); - this.end(JSON.stringify(payload)); - return this; - }; -} - -async function runScenarioRequests(baseUrl: string, requests: number, concurrency: number): Promise { - let completed = 0; - - const worker = async () => { - while (completed < requests) { - completed += 1; - const requestNumber = completed; - if (requestNumber > requests) { - return; - } - - const response = await fetch(`${baseUrl}/profile`, { - headers: { - 'x-profile-request': String(requestNumber), - 'x-profile-scenario': 'memory', - }, - }); - - if (!response.ok) { - throw new Error(`Unexpected response status ${response.status}`); - } - - await response.arrayBuffer(); - } - }; - - await Promise.all(Array.from({ length: concurrency }, () => worker())); -} - -async function executeMiddlewareChain( - req: IncomingMessage, - res: ServerResponse, - middleware: Array<{ use: (req: any, res: any, next: (error?: unknown) => void) => void | Promise }>, -): Promise { - let index = 0; - - const runNext = async (): Promise => { - if (res.writableEnded) { - return; - } - - const current = middleware[index]; - index += 1; - - if (!current) { - res.statusCode = 200; - res.setHeader('content-type', 'application/json'); - res.end(JSON.stringify({ ok: true })); - return; - } - - await new Promise((resolve, reject) => { - try { - const maybePromise = current.use(req as any, res as any, (error?: unknown) => { - if (error) { - reject(error); - return; - } - resolve(); - }); - - if (maybePromise && typeof (maybePromise as Promise).then === 'function') { - (maybePromise as Promise).then(resolve).catch(reject); - } - } catch (error) { - reject(error); - } - }); - - if (!res.writableEnded) { - await runNext(); - } - }; - - await runNext(); -} - -async function main() { - const args = parseArgs(); - const scenario = getScenario(args.scenario); - const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); - const outputDir = join(args.outputDir, `${scenario.name}-${timestamp}`); - - await mkdir(outputDir, { recursive: true }); - - const server = createServer(async (req, res) => { - try { - addExpressLikeHelpers(req, res); - await executeMiddlewareChain(req, res, scenario.middleware as any); - } catch (error) { - res.statusCode = 500; - res.setHeader('content-type', 'application/json'); - res.end( - JSON.stringify({ - ok: false, - error: error instanceof Error ? error.message : String(error), - }), - ); - } - }); - - await new Promise(resolve => server.listen(0, '127.0.0.1', () => resolve())); - const address = server.address(); - const port = typeof address === 'object' && address ? address.port : 0; - const baseUrl = `http://127.0.0.1:${port}`; - - try { - global.gc?.(); - const before = toMemorySummary(); - await writeHeapSnapshot(join(outputDir, 'before.heapsnapshot')); - - await runScenarioRequests(baseUrl, args.requests, args.concurrency); - - global.gc?.(); - const after = toMemorySummary(); - await writeHeapSnapshot(join(outputDir, 'after.heapsnapshot')); - - const summary = { - scenario: scenario.name, - description: scenario.description, - requests: args.requests, - concurrency: args.concurrency, - outputDir, - before, - after, - delta: { - rssMb: Number((after.rssMb - before.rssMb).toFixed(2)), - heapTotalMb: Number((after.heapTotalMb - before.heapTotalMb).toFixed(2)), - heapUsedMb: Number((after.heapUsedMb - before.heapUsedMb).toFixed(2)), - externalMb: Number((after.externalMb - before.externalMb).toFixed(2)), - }, - leakRiskNotes: scenario.leakRiskNotes, - }; - - await writeFile(join(outputDir, 'summary.json'), JSON.stringify(summary, null, 2), 'utf8'); - - console.log('Memory profiling completed'); - console.log(JSON.stringify(summary, null, 2)); - } finally { - await new Promise((resolve, reject) => { - server.close(error => { - if (error) { - reject(error); - return; - } - resolve(); - }); - }); - } -} - -main().catch(error => { - console.error('Memory profiling failed', error); - process.exit(1); -}); diff --git a/benchmarks/memory/scenarios.ts b/benchmarks/memory/scenarios.ts deleted file mode 100644 index a2df1298..00000000 --- a/benchmarks/memory/scenarios.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { NestMiddleware } from '@nestjs/common'; -import { LoggingMiddleware } from '../../src/common/logging/logging.middleware'; -import { HeaderValidationMiddleware } from '../../src/security/middleware/header-validation.middleware'; -import { - CircuitBreakerMiddleware, - CircuitBreakerService, -} from '../../src/middleware/advanced/circuit-breaker.middleware'; - -export interface MemoryProfileScenario { - name: string; - description: string; - middleware: NestMiddleware[]; - leakRiskNotes: string[]; -} - -export const MEMORY_PROFILE_SCENARIOS: Record = { - baseline: { - name: 'baseline', - description: 'No middleware, only the terminal request handler', - middleware: [], - leakRiskNotes: ['Use this as the control profile for snapshot diffs.'], - }, - 'header-validation': { - name: 'header-validation', - description: 'Logging middleware plus header validation', - middleware: [new LoggingMiddleware(), new HeaderValidationMiddleware()], - leakRiskNotes: [ - 'Confirms header sanitization does not retain per-request header objects.', - 'Verifies correlation-id context does not leak across requests.', - ], - }, - 'circuit-breaker': { - name: 'circuit-breaker', - description: 'Circuit breaker middleware with in-memory state tracking', - middleware: [ - new CircuitBreakerMiddleware( - new CircuitBreakerService({ - failureThreshold: 5, - retryInterval: 1000, - paths: ['/'], - }), - ), - ], - leakRiskNotes: [ - 'Tracks whether response.end wrapping leaves lingering closures.', - 'Confirms circuit state counters remain bounded under sustained traffic.', - ], - }, - combined: { - name: 'combined', - description: 'Logging, header validation, and circuit breaker together', - middleware: [ - new LoggingMiddleware(), - new HeaderValidationMiddleware(), - new CircuitBreakerMiddleware( - new CircuitBreakerService({ - failureThreshold: 5, - retryInterval: 1000, - paths: ['/'], - }), - ), - ], - leakRiskNotes: [ - 'Approximates a realistic middleware chain for cumulative retention analysis.', - 'Useful for spotting interaction leaks between request wrapping and response mutation.', - ], - }, -}; - -export function getScenario(name: string): MemoryProfileScenario { - return MEMORY_PROFILE_SCENARIOS[name] || MEMORY_PROFILE_SCENARIOS.combined; -} diff --git a/build_output.txt b/build_output.txt deleted file mode 100644 index ff308feaa0fd639d22e8ffc8e7d00ed75426e85d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33694 zcmeI5+j1Mn5r+3VRe6HkAg)wMB^D`Cqz<%WTejrbam8{h+P-k5Y>K1~7Eb}GNQ|RA zdXoQ}Mq_4o2OzLmfS`DOs-7Oqml zOO4xFy`3ZVikdr>KG4FE#&M`CTl)N__`bMX+|ut;^=h|RRnK1PzGunNimvVJ>Oa-n zT^+6H`f0fHhVI+y)p1kDYx=uUxs_xZ5vbJ)?zAv0XgU z-8c1jx8G~7d=>6F33s0r=PF5iOB&yfdU#sA3N`NO475I0xlnW zY8#55g#Xa?b!cN<<$kaFy~h6(ZT(SWr}sx+KM}RgG@7UCNmms3T)lsyV=t3_gPAXN z?MxhjQoEwW6MgnYU#>0p&=3)2Jh3{;=vom?8SgNfZ>gO#^$L1FEv~7B?~A_|@9O(& zwRsqNvR^z9%|Paf&d2u7bQgTBj`veh`apl@#ou(aqoX*62Wrc3__;=8GV*1h&vW5_ zU$i<_tA{#+%*WE!2LJhh-Pm+AZG@3Gs8U4?t`mIJ< zGdVGtL7rk;qa0O{n7K_v+MlRi7rWXw8fE$V+Pv?Hk}ISsqeGfSl2(QMIvbu>e5kig0)= z&HGfy>h^!#6P_rsta));*Ubj9euBX#0g0z7!MxB>Juih)G&HmF6a6y%yA(9}&nn^g zMC&q-`0tgT6ugn{ze+eQQ=G>1Xe}_yo(rQF;|mQ5jj#w$ggA67CBPUSf=XY7h|2Yre366ZQI*n7Owmn1Y*s>Ry#9i9KQQ1>6( z@Er}idH>N{_xac99I@A?ZxCze=&t+`x9?(m!;c~&?8s~MaSWQl+Qh}W5&a%{GCe9%~~Cie*K_ln5EIFk+NMK8Y;s>lzV3d^dbK;tP~~T>PZ7 zyMa5gE{lwMi&qB?5vTd16fKT2A7y#o+Y9vC5q*f*?aKlpf{*_UmCL_k#1rp&kS*j^ zDeaXlA!6X(ntftlCekl7w z{byBVwQos%BA?&aM?TgO>mv_>#k?BinArQC?)^cnafGa!%}8V_rP;2oU{4;Yjn#0^ z6V+$B;T=(qIoc_VcR;%y-A}zaV%m;nMtB%--VNjXYp*v4@*Qpb9_M#HgJ$OiGGHE} z)fwffQ|e8E7aFN#>O=n(Bk#5J{s?%ZGcy~qS>S!9cz0fm ziuXs73Z$5M;eAC)ST6DFR^j?;84 zF|W;=o~6gtdoN#JSXpB1^sed?Z7gO8&0MpbA)Fg>SG#%K0kJE7R?0++E#;=Z4SnVX&sk_Sd+rR{fLaa|s%_ zj_%=S+}`6}o4I195ndv3i#GjmkHzL@i?xMkG6U>mDGkGWHCFzrKR=9z_SjBa2p<*S zv&Zyc3us;5g!g9=U9$LH)96xFvp$ptCic}WJ`UQQe6D99I(rcGmSrnO9Om_VYA>PR z(d)5R!#v0vuI0z=3;BsT?|srSlFiwcyg`joWp3Ck9=&M>6zF|kiYC;7!qnO2WJ>$re5#+pD9s?fV@C;aQBh7uKz4W=tCVu%%A%8PO|GWjG zq2*tg-$cI0M?I_FsiVeSG6jbmG5Aj%NL|)4zxS&0rFq|x2b9uP9 zU!leL*r?W!!$-A@Kj~3Dzb&~W^3L_@wMQYQd?vnuzB0z9k1w!xxfr`SVVwK2FlO>! z<)(9bfw%EI?p$dooa(~#_;NA3IbqyvzA&3=papJoNF4th*d26NisS0>IJma8+{2Kk zdaD2AS~s2Z>96ghaaHGh)5l+FmhH-NA$QklGCrnrwdCgid^zTDdJ}EM+05f$X*~Rt zGXk1o2i!2;t7|VhcFOdaOfOc~1Jc^6cAm9A%sXnsmzYG?KpA3|lVHU0!DxL?k?|uT zmo;}TX)V=gFup$VJ99cDUMt)F)5pX(x`OB4$(cUYe=@NrnQe^!Z^LY}ou$h7_{i6j zLrcD-`WUrrQw80uZCEfDVr8y2Z7UC$c$hx{W&2=wbc~D+uKB*TaaRp?m&Mm((Tygou>!`EofC~R zK5yiEckPKj$D(oh>bY_mkTdoeWe@BXQHyf<9V{3Vvvu^*QWh*Tf8fY}0^LSrUh{m)z&7(@?z2-jX;}Cs9ZlCGOoDL*khMLPGP1}g0 zifcB^r;L?7(;4G8`n0@PBb2hel>eo= z*y$YYl|Dte+S zP47JTWfxI24fcHbDt0~Z&Uh(p_=R+~-_>09X)ntEyvx2*yp3dgTCb2-s-NrT; zR{QK$k*X-oV{MfAD<4-U-+IuMQRgw^&04b8TZ*wscT|dRuAv>*oK@~%W8(L+b_)lw z2>+~a{EBhkUqd@fdd}E(Vtx^<9^04ik!p?a^2vEDDHS5`qEC%~T<+ywub*+3yQqn= zc*%Mm+y^4U<@#*Y%d)@TYt=uFqZxbz<#Jc^sC8aCU(5E^AXK)6*UiMbO7XfW5664f z%8-c$17{Ijew2OuZQ}|-|PW5NOc67FE@e+UM46$}=FTU#vi^sCokR#q1 z#6IBkh
C&cifAMq+{jny7jc+OOoKG2`*y=%m^sL`TTv}RE^%CH~SLD*9i*&`yv z$|`#U6RG2^jf}Y-sYq#UE5hy2=VAS(UOkdBxF{={d~8Df2jQfsA|Bc^~Ue z^H}hxp)Y9lV|&Bckto94ZnHY?f*Q1Ub&L(9_@%uzBLB9(xsT$$dU+Bk%=<>Lm=&b{fOCvO|k-qpcQ9D`BUW{@iC zsyiAuZL9h|rGGs3($nKa+?BsN%g+ZVhRyM@?nwIiD0CKC?O!$)1TL zN$Fp|zZoZHDFx}iU6Ct{^{@qvG}?|G!|cW;dv?(KrJh}TU)JY|>`x*GW?%C*^}1h_ z(jnz(?*1xQ2j@IRPF9bmFKz4DwSc#Wv)=~4!gCCBJWVN(^0a*CWZaxSAIbLdR;m&j zuQanai8Yho=k-5S{2;y|3#?c+s(FS7D#^MIaSD7vi&*f+C8W#VR@>1!2^o~H^q>5o zdWIf;rM-RLBPc{dh+W_Z<3U~=ceKnMkLq|mc{>EH>~Wbv9&<`ZLyE;l(q2KQ@vk diff --git a/build_output_2.txt b/build_output_2.txt deleted file mode 100644 index e69069a399f392a4850dae00e4fa0fa21f8fe664..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17746 zcmeI4Yg1dv5r*e;s`3l+MMb3+oUD-nv%X}rSueH|XA?Uic$2EFlvf}bv*zMRVu29n zrzd%zX|-m~MHeJ6)W+okj?S4g-P6~%dq)26e|{Q%621tH@Gf-2k$&%lH=z~w!eO`_ zwso}=-iD4owZoTTB`k+K@yEt@G~!re_x050>FV===4yr4nzgM@z0i+O8R4TYO07!g zP+T!{qr?Lg4z-R0J$a~~pM`J3gYcO?_r%psXzJ=ne09WiPoG*EyQj6X$}_Evwf1$V zA3yaqh8gbYt%rlT)^xo#ybHbj$x668eAdvs&cTY_>WBlR+#QZE?wGw1w!&Y+s@`4| zHRqfs8{)JjK6)AhwZ-r#^89t=cu{xJ)=r$at9v`*eP7&j|3D-6br0ICi#ZtG*XOP@ zgnm1^w;0a#+hhQ3=pbFRc^G!Xui|^{$XEIPp=M!z-YY-b(F`3uhhAHJ_v5I?gFDO$ zrDJi~9yfY5Xa!;I&4cR_0_B>-&e^G;7=tN5@gVF2!xVxf`X}kF%OC`{AW{93>MU zv#HtoW94G2@lkske;6J|Zt7%hEBYp`uqU1vUAOZ0vWMlU8D?on##jLwUePCu5Z(9* z`oGjY_qc9ceeRQu7+sS8zKRm+OXJ6y`<1MHS$|I>omGwfL^OQXe}~Kb$E=OPKX~34 zNOo5ob>%P5w2Ifd_A&Wir1V_R`tniiYey2nCeR?ymIkpQ#Tm0~o1++WmbKz#%{5N; z4@D<=-z`zVem~XUP0=KRVZTo#H~jaV?k9RgFJ>>V_o*bluYYIZ&$?15jYwuurJ+^4iQ|zwyd8y; z;WN(>_#9@&SKoG(F=Oz*i8h(FGur%FO8tU+n@o3(nCjd1WoEYX)MWYk{n~B~(f-b{*iYhFXbiNS$Yg ziU5}Bxoe(qthEq3w`0V%8jARmBV)&`M~a`WK|>8oVL?^NL&?guMu*~eicU>cb@1?3 zvlDlk!-%z!^=rP0t3bwYh0#Ik&B!I)j#n{uwqp&zOilH3EaF)=z`F!!32oV$sb=Y# z*c+*eYib7WBeiDKC^SyR|E-vV=^?p{z(QpSk$b3%LErsI0}3WD*97>=bnmz!M>S>s z&>=PIiT-XzeiQFY75sEj1eH^6RH{<9K#S4V5TV6!>m zTA#BAwWjyiD_-$P>)4g9yq81<#Dd+P$(iLmN~K9oJ(K-nxhZ?P_aHOFSZ)vIJIqTh zP6i}yK-Icdb#&3V;k|bFT$Yq79FROT=*ql}-f*JdUx<_BozHZ~?6=M?8(Jm)SzKvO zBdw}j-&$6O{>7wJ^#s$nTUxS5{J=bj$ONVDO15<-O%jFS_+j|De1WQ)&u(vfk}o6v zsk!Ki(BbLCeu#BxmIinVJvPF>^v@`rD~sLI&v(LjP=-6a*0@W&a`iyI>`xN+vtL1P z(%X66ldhdF=lDZ->pgjt(<8&=-uj?WMc&q`lDzO8qQ|(7@kejXv&c>HRy6LGmh80X zt#zJC4kO}i%h$|X>0wZ3;N?WA_k;V`6IC5(s``|e$?nUs{QPTKoWC`@??W&7|4sM( zB=h;NSa~(;TSRdkyLT6(iD6#QAyL((_g;(WI1C1t~E zCQN$Z>az2oai3P5u2RO!ubdl~--or=yRum4Ah*|h!@ILt>#FvV%GR3KT=Y`Vm{l9r zZCVgoeWG2R$3i;KWe*FnQ^kHMqYU#Mgs0NA_4Ud9tv!ulf8;FA<9ig7dv@U5 z$)lhK3eNWz%N#kzL=vnv-@PqXA?$Xw!*8O@$|KDiPE~i}$!|uCqJL4Ygva4{=gsVO zQ9EXTl}F=stf(*4z9oKI;yXK=cUFOhPBfRZK2w_SvdFbiGEn| zd^52_2P&?v%DP9BDb;gGHJ$2|j~0ECEqXe8p4K+UTX?;-xRur0a{W8GeUUpp+So@M zvz^#_dntBK9BsJOfcC5_RL(cPqmp`FmV?M5)I03y&@BPAacaqGo^l`6>6I-t&tdcB zCF(Cu7_paF?ZV{vCFg~cZgAX+8MWMLpWJP9gyz_YjKmK#3^j7Hgq~S_FLycie8AS= z@TR0lKgZ5|<^9=Zy+6L9co6QZhm&g89Hph*3FpoE1BI90O!CQP!<&B#FVv&Go{V3| zxpV5$&t>k<>NMofwqn1`cMI$U9{Y}Y$I$HB>LJI5bT{+fu|`H%GIaQ9FoM1s@U_FuXGrL5=#p4hfG64_P%VpZkeRWt6nS;CG zGereI*V>nEs`&ZxdJXGYpRyPgQe2p=dYiV_uoG>ZILp~L&Pw4uC#odU840{*n$80< zOf|`@orhc|9u4ySF6%th@oAlhRy^N<51FrDtP3%XJZ@G`BFSh}Kh5K;{q=}^Jr;j& zq{ZKvvtKc-#qY|}`y=AfW{l?@MPSaMOtyPuSj`Tzb=-2vB%S6RH?k4^OXIF;?UOAX zepBCXS$St#Su9B&r@}dPojmVq+@wz3biOd1N7#8-qCWZ5b~Q&Kz5{j5Qs*s?>8VR+ z5k2|ewBKV`)3+GzM>Om{{Ktr1!4Y76W&~k#k|6Kz!mF>{J@3@vOeUAMm5z0N=n7C&RhV2?gZG&aY7eQ*(aBzh41A zw+GMc1P3zT9Z<9VYsPRQZa-EPAVNFw3}<$_mQ!G?xms=H+HoF?P9yw6R1%IfNpj`} z9`n@|`XWs7;VAzl?wD$WPwh9 zHe7P2^i3STSwVjoD=-vdc4c+~&;G3dY{t*PZ)q%;xxSuE9NM>aT)%Xz?HsVbPe;h^ zybu>iCE0L#X4cF(WGvV{?S08wzSL9fvLC+JZ+wume!DToQu&tcByq{rs6C9LmH0c? zqx*UHzb;4jRZac)tsvn6zbe{A`gENZvX)`H>x>R%fBk>754V%LzeJB@G5OWiTTeYU zf}{Lk0WM_*l}zdy|6IZC}b zn(!Q5=e>#dTm$~bY?8lviKqN|GbKJVUi}xS1yyQi*2j5XSjYmnk|0cye>lK63BI0d~-f+UcDYUGw)Q&9-5xahBfIk zvwPw5zfkYs`{*m)Ii@PL^YQcm=!CRlpM*Nl{x^tTtQzf`>vT}kY54L!lzm5mn$o`S z?cEc)AoMNl|CE^Klpp<&d>1VD_%a3|DyI{Yb#{_V*zAPgWv-CZ#dcuF`8*syRW#%K V1N4!IKhX4Z*-NUOZ)Lrk{{d;L=Z^pY diff --git a/claims.e2e-spec.ts b/claims.e2e-spec.ts deleted file mode 100644 index 45cec085..00000000 --- a/claims.e2e-spec.ts +++ /dev/null @@ -1,131 +0,0 @@ -/** - * @fileoverview End-to-end tests for the claims lifecycle. - * @issue #209 - */ - -import { Test, TestingModule } from '@nestjs/testing'; -import { INestApplication, HttpStatus } from '@nestjs/common'; -import * as request from 'supertest'; -import { AppModule } from '../src/app.module'; -import { PrismaService } from '../src/database/prisma/prisma.service'; -import { AuthService } from '../src/auth/auth.service'; - -describe('Claims Lifecycle (e2e)', () => { - let app: INestApplication; - let prisma: PrismaService; - let authService: AuthService; - - let claimantToken: string; - let approverToken: string; - let claimantId: string; - let approverId: string; - let propertyId: string; - let claimId: string; - - beforeAll(async () => { - const moduleFixture: TestingModule = await Test.createTestingModule({ - imports: [AppModule], - }).compile(); - - app = moduleFixture.createNestApplication(); - await app.init(); - - prisma = app.get(PrismaService); - authService = app.get(AuthService); - - // -- Test Setup -- - // 1. Clean database - await prisma.claim.deleteMany(); - await prisma.property.deleteMany(); - await prisma.user.deleteMany(); - - // 2. Create users with different roles - const claimant = await prisma.user.create({ - data: { - email: 'claimant@test.com', - password: 'password', - role: 'USER', - }, - }); - claimantId = claimant.id; - - const approver = await prisma.user.create({ - data: { - email: 'approver@test.com', - password: 'password', - role: 'ADMIN', - }, - }); - approverId = approver.id; - - // 3. Create a property to file a claim against - const property = await prisma.property.create({ - data: { - name: 'Test Property for Claims', - ownerId: approverId, // An admin owns the property - }, - }); - propertyId = property.id; - - // 4. Generate auth tokens - claimantToken = (await authService.login(claimant)).accessToken; - approverToken = (await authService.login(approver)).accessToken; - }); - - afterAll(async () => { - await app.close(); - }); - - it('should allow a user to create a new claim (POST /claims)', async () => { - const response = await request(app.getHttpServer()) - .post('/claims') - .set('Authorization', `Bearer ${claimantToken}`) - .send({ - propertyId: propertyId, - description: 'E2E Test: My roof is leaking.', - type: 'DAMAGE', - }) - .expect(HttpStatus.CREATED); - - expect(response.body).toHaveProperty('id'); - expect(response.body.status).toEqual('PENDING'); - expect(response.body.userId).toEqual(claimantId); - claimId = response.body.id; - }); - - it('should allow an admin to approve a pending claim (POST /claims/:id/approve)', async () => { - const response = await request(app.getHttpServer()) - .post(`/claims/${claimId}/approve`) - .set('Authorization', `Bearer ${approverToken}`) - .send({ - notes: 'E2E Test: Approved for repair.', - }) - .expect(HttpStatus.OK); - - expect(response.body.id).toEqual(claimId); - expect(response.body.status).toEqual('APPROVED'); - }); - - it('should not allow a regular user to approve a claim', async () => { - // Attempt to approve with the claimant's token - await request(app.getHttpServer()) - .post(`/claims/${claimId}/approve`) - .set('Authorization', `Bearer ${claimantToken}`) - .expect(HttpStatus.FORBIDDEN); - }); - - it('should allow an admin to settle an approved claim (POST /claims/:id/settle)', async () => { - const response = await request(app.getHttpServer()) - .post(`/claims/${claimId}/settle`) - .set('Authorization', `Bearer ${approverToken}`) - .send({ - settlementAmount: 5000, - transactionHash: '0x' + 'a'.repeat(64), - }) - .expect(HttpStatus.OK); - - expect(response.body.id).toEqual(claimId); - expect(response.body.status).toEqual('SETTLED'); - expect(response.body.settlementAmount).toEqual(5000); - }); -}); \ No newline at end of file diff --git a/dashboard.dto.ts b/dashboard.dto.ts deleted file mode 100644 index eeb8f339..00000000 --- a/dashboard.dto.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @fileoverview DTOs for the admin dashboard endpoint. - * @issue #206 - */ - -import { Type } from 'class-transformer'; -import { IsDate, IsOptional } from 'class-validator'; - -export class AdminDashboardQueryDto { - @IsOptional() - @IsDate() - @Type(() => Date) - startDate?: Date; - - @IsOptional() - @IsDate() - @Type(() => Date) - endDate?: Date; -} - -export class AdminDashboardResponseDto { - userStats: { - total: number; - byRole: Record; - }; - projectStats: { - total: number; - byStatus: Record; - }; - donationStats: { - totalAmount: number; - totalCount: number; - }; - platformFees: { - totalCollected: number; - }; - recentActivity: any[]; - query: { - startDate?: Date; - endDate?: Date; - }; -} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 18f5ff45..00000000 --- a/docker-compose.yml +++ /dev/null @@ -1,96 +0,0 @@ -version: '3.8' - -services: - # PostgreSQL Database - postgres: - image: postgres:15-alpine - container_name: propchain-postgres - restart: unless-stopped - environment: - POSTGRES_DB: propchain - POSTGRES_USER: postgres - POSTGRES_PASSWORD: password - ports: - - '5432:5432' - volumes: - - postgres_data:/var/lib/postgresql/data - - ./scripts/init-db.sql:/docker-entrypoint-initdb.d/init-db.sql - healthcheck: - test: ['CMD-SHELL', 'pg_isready -U postgres'] - interval: 10s - timeout: 5s - retries: 5 - - # Redis Cache - redis: - image: redis:7-alpine - container_name: propchain-redis - restart: unless-stopped - ports: - - '6379:6379' - volumes: - - redis_data:/data - healthcheck: - test: ['CMD', 'redis-cli', 'ping'] - interval: 10s - timeout: 3s - retries: 5 - - # NestJS Application - api: - build: - context: . - dockerfile: Dockerfile - target: runner - container_name: propchain-api - restart: unless-stopped - env_file: - - .env.development - environment: - DATABASE_URL: postgresql://postgres:password@postgres:5432/propchain - REDIS_HOST: redis - REDIS_PORT: 6379 - - ports: - - '3000:3000' - volumes: - - ./logs:/app/logs - - ./uploads:/app/uploads - depends_on: - postgres: - condition: service_healthy - redis: - condition: service_healthy - healthcheck: - test: ['CMD', 'curl', '-f', 'http://localhost:3000/api/health'] - interval: 30s - timeout: 10s - retries: 3 - start_period: 40s - - # Nginx Reverse Proxy (Optional) - nginx: - image: nginx:alpine - container_name: propchain-nginx - restart: unless-stopped - ports: - - '80:80' - - '443:443' - volumes: - - ./nginx/nginx.conf:/etc/nginx/nginx.conf - - ./nginx/ssl:/etc/nginx/ssl - depends_on: - - api - profiles: - - production - -volumes: - postgres_data: - driver: local - redis_data: - driver: local - -networks: - default: - name: propchain-network - driver: bridge diff --git a/docs/API_SECURITY_GUIDE.md b/docs/API_SECURITY_GUIDE.md deleted file mode 100644 index 8bc09b60..00000000 --- a/docs/API_SECURITY_GUIDE.md +++ /dev/null @@ -1,564 +0,0 @@ -# API Security Guide - -This guide covers the comprehensive API security implementation in the PropChain Backend project to ensure robust protection against various security threats. - -## Table of Contents - -- [Overview](#overview) -- [Security Headers](#security-headers) -- [Request Validation and Sanitization](#request-validation-and-sanitization) -- [Threat Detection and Prevention](#threat-detection-and-prevention) -- [Authentication Hardening](#authentication-hardening) -- [Authorization and RBAC](#authorization-and-rbac) -- [Abuse Detection and Prevention](#abuse-detection-and-prevention) -- [Security Testing](#security-testing) -- [Configuration](#configuration) -- [Best Practices](#best-practices) - -## Overview - -The API security system provides comprehensive protection against: - -- **Injection Attacks** - SQL injection, XSS, NoSQL injection -- **Authentication Threats** - Token manipulation, brute force attacks -- **Authorization Bypass** - Privilege escalation, role bypass -- **Abuse and DDoS** - Rate limiting, burst protection -- **Data Exposure** - Information leakage, insecure headers -- **Session Security** - Session hijacking, fixation - -## Security Headers - -### Automatic Security Headers - -The `SecurityHeadersInterceptor` automatically adds comprehensive security headers to all API responses: - -```typescript -// Applied headers include: -- Content-Security-Policy: Prevents XSS and code injection -- Strict-Transport-Security: Enforces HTTPS -- X-Frame-Options: Prevents clickjacking -- X-Content-Type-Options: Prevents MIME sniffing -- Referrer-Policy: Controls referrer information -- Permissions-Policy: Restricts browser features -- X-XSS-Protection: Enables XSS filtering -``` - -### CSP Configuration - -```typescript -// Default CSP Policy -const cspPolicy = [ - "default-src 'self'", - "script-src 'self' 'unsafe-inline' 'unsafe-eval'", - "style-src 'self' 'unsafe-inline'", - "img-src 'self' data: https:", - "font-src 'self'", - "connect-src 'self'", - "frame-ancestors 'none'", - "base-uri 'self'", - "form-action 'self'" -].join('; '); -``` - -## Request Validation and Sanitization - -### Input Sanitization - -The `RequestValidationInterceptor` provides comprehensive request validation: - -```typescript -// Automatic sanitization includes: -- Null byte removal -- Control character filtering -- SQL injection pattern detection -- XSS pattern detection -- Path traversal prevention -- Request size validation -``` - -### Validation Rules - -```typescript -// Suspicious patterns detected: -- - - - `; - } -} -``` - -That's it! CSP is now protecting your application. - ---- - -## ⚙️ Configuration - -### Trusted Sources by Content Type - -#### Scripts -```typescript -{ - scriptCdns: [ - 'https://cdn.jsdelivr.net', // jsDelivr - 'https://unpkg.com', // unpkg - 'https://www.google-analytics.com' // Analytics - ] -} -``` - -#### Styles -```typescript -{ - styleCdns: [ - 'https://fonts.googleapis.com' // Google Fonts - ] -} -``` - -#### Images -```typescript -{ - imageCdns: [ - 'https://images.unsplash.com', // Unsplash - 'https://cdn.example.com', // Your CDN - 'data:', // Data URIs - 'blob:' // Blob URLs - ] -} -``` - -#### Fonts -```typescript -{ - fontCdns: [ - 'https://fonts.gstatic.com', // Google Fonts - 'https://cdn.jsdelivr.net' // jsDelivr fonts - ] -} -``` - -#### Connections (API/Fetch) -```typescript -{ - apiEndpoints: [ - 'https://api.propchain.com', // Your API - 'https://www.google-analytics.com', // Analytics - 'https://js.stripe.com' // Stripe - ] -} -``` - -#### Frames (Prevent Clickjacking) -```typescript -{ - frameAncestors: ["'none'"] // Default: block all framing -} -``` - ---- - -## 📖 Usage Examples - -### Example 1: Inline Script with Nonce - -```typescript -import { Controller, Get, Req } from '@nestjs/common'; -import { CspRequest } from './security/middleware/csp.middleware'; -import { CspUtilityService } from './security/services/csp-utility.service'; - -@Controller('dashboard') -export class DashboardController { - constructor(private cspUtility: CspUtilityService) {} - - @Get() - getDashboard(@Req() req: CspRequest) { - const nonce = req.cspNonce; - - // Create CSP-compliant inline script - const analyticsScript = this.cspUtility.createInlineScript(` - // Initialize analytics - window.analytics = window.analytics || []; - console.log('Analytics initialized'); - `, nonce); - - return { - html: ` - - - - ${analyticsScript} - - -

Dashboard

- - - `, - }; - } -} -``` - -### Example 2: Dynamic CDN Configuration - -```typescript -// For multi-tenant applications with different CDNs -const customCdnConfig = { - scriptCdns: [ - process.env.TENANT_CDN_URL || 'https://cdn.default.com' - ] -}; - -// Validate before using -const validation = cspUtility.validateThirdPartyDomain( - 'https://cdn.example.com', - 'script' -); - -if (validation.valid) { - // Safe to use -} else { - console.error(validation.reason); -} -``` - -### Example 3: Testing New Policies - -```typescript -// Enable report-only mode to test without breaking anything -cspUtility.enableReportOnlyMode(); - -// Monitor violations in logs -// Once confident, switch to enforcement -cspUtility.enableEnforcementMode(); -``` - ---- - -## 📊 Monitoring & Reporting - -### Violation Reports - -Browsers automatically send POST requests to `/api/v1/security/csp-report` when they detect violations. - -**Example Violation Report:** -```json -{ - "csp-report": { - "document-uri": "https://app.propchain.com/dashboard", - "referrer": "https://google.com", - "blocked-uri": "https://malicious.com/evil.js", - "violated-directive": "script-src 'self'", - "effective-directive": "script-src", - "original-policy": "script-src 'self' 'nonce-abc123'", - "disposition": "enforce", - "source-file": "https://malicious.com/evil.js", - "line-number": 42, - "column-number": 10 - } -} -``` - -### Log Output - -Violations are logged with severity levels: - -``` -[CSP Violation] Severity: critical | Directive: script-src | Blocked: https://malicious.com/evil.js | IP: 192.168.1.100 - -[SECURITY EVENT] Potential CSP attack from 192.168.1.100 - Blocked URI: https://malicious.com/evil.js - Directive: script-src -``` - -### Severity Levels - -| Severity | Directive | Description | -|----------|-----------|-------------| -| **Critical** | `script-src` | Script injection attempts | -| **High** | `style-src`, `frame-*` | Style injection, clickjacking | -| **Medium** | `connect-src` | Unauthorized API connections | -| **Low** | Other | Miscellaneous violations | - ---- - -## 🔧 Troubleshooting - -### Issue: Legitimate Script Blocked - -**Symptoms**: Console shows CSP blocking your own scripts - -**Solution**: -1. Check if script is inline → Add nonce -2. Check if from CDN → Add CDN domain to `scriptCdns` -3. Verify script source URL matches whitelist - -```typescript -// Option 1: Add nonce to inline script - - -// Option 2: Add CDN to environment variables -CDN_SCRIPT_3=https://your-cdn.com -``` - -### Issue: Styles Not Loading - -**Symptoms**: CSS from Google Fonts not applying - -**Solution**: Ensure `style-src` includes Google Fonts: - -```bash -# .env -CDN_STYLE_1=https://fonts.googleapis.com -``` - -### Issue: Analytics Not Working - -**Symptoms**: Google Analytics or other tracking blocked - -**Solution**: Add analytics domains to both `script-src` and `connect-src`: - -```bash -ANALYTICS_DOMAIN=https://www.google-analytics.com -``` - -### Issue: Payment Gateway Fails - -**Symptoms**: Stripe/PayPal integration errors - -**Solution**: Add payment gateway domains: - -```bash -STRIPE_DOMAIN=https://js.stripe.com -PAYPAL_DOMAIN=https://www.paypal.com -``` - ---- - -## 🎓 Best Practices - -### DO ✅ - -- **Use nonces for inline scripts** instead of `unsafe-inline` -- **Test in report-only mode** before enforcing new policies -- **Monitor violation reports** regularly for attack patterns -- **Use specific CDN domains** rather than wildcards -- **Keep policies environment-specific** (dev vs prod) -- **Log all violations** for security analysis -- **Update whitelists** when adding new integrations - -### DON'T ❌ - -- **Never use `unsafe-eval`** in production -- **Avoid `unsafe-inline`** for scripts (use nonces instead) -- **Don't wildcard entire domains** (`*://*.com`) -- **Don't ignore violation reports** (they indicate attacks) -- **Don't enable too many CDNs** (increases attack surface) -- **Avoid inline event handlers** (`onclick="..."`) - ---- - -## 📝 Environment Policy Differences - -### Development Mode -```typescript -{ - reportOnly: true, // Don't break things - enableNonce: false, // Easier debugging - allowUnsafeInline: true, // For hot reload - allowUnsafeEval: true, // For debugging tools -} -``` - -### Production Mode -```typescript -{ - reportOnly: false, // Enforce policy - enableNonce: true, // Secure inline scripts - allowUnsafeInline: false, // Block unsafe inline - allowUnsafeEval: false, // Block eval -} -``` - ---- - -## 🔒 Security Considerations - -### XSS Attack Prevention - -This CSP implementation blocks: - -1. **Inline Scripts Without Nonce** - ```html - - - - - - ``` - -2. **External Scripts From Untrusted Sources** - ```html - - - - - - ``` - -3. **Event Handler Injections** - ```html - - -
Click
- ``` - -4. **Data URI Injection** - ```html - - - ``` - -### Clickjacking Prevention - -The `frame-ancestors 'none'` directive prevents your site from being embedded in iframes, protecting against clickjacking attacks. - ---- - -## 📈 Performance Impact - -- **Minimal overhead**: ~0.1ms per request for nonce generation -- **Header size**: CSP headers add ~500-800 bytes -- **Browser caching**: Policies cached by browsers -- **No runtime impact**: All checks happen at header level - ---- - -## 🧪 Testing CSP - -### Manual Testing - -1. Open browser DevTools Console -2. Look for CSP violation messages -3. Try loading resources from non-whitelisted domains -4. Test inline scripts without nonces - -### Automated Testing - -```typescript -describe('CSP Headers', () => { - it('should include CSP header', async () => { - const response = await request(app.getHttpServer()) - .get('/api/test') - .expect(200); - - expect(response.headers['content-security-policy']).toBeDefined(); - }); - - it('should block malicious scripts', async () => { - // Attempt to load script from non-whitelisted domain - // Should be blocked by browser CSP enforcement - }); -}); -``` - ---- - -## 📚 Additional Resources - -- [MDN CSP Documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) -- [W3C CSP Specification](https://www.w3.org/TR/CSP/) -- [CSP Evaluator Tool](https://csp-evaluator.withgoogle.com/) -- [Report URI](https://report-uri.com/) - ---- - -**Last Updated**: March 27, 2026 -**Version**: 1.0.0 -**Maintained by**: PropChain Security Team diff --git a/docs/DATABASE_OPTIMIZATION_GUIDE.md b/docs/DATABASE_OPTIMIZATION_GUIDE.md deleted file mode 100644 index 5d75286a..00000000 --- a/docs/DATABASE_OPTIMIZATION_GUIDE.md +++ /dev/null @@ -1,497 +0,0 @@ -# Database Optimization Guide - -This guide covers database optimization strategies and tools implemented in the PropChain Backend project to ensure optimal performance, scalability, and reliability. - -## Table of Contents - -- [Overview](#overview) -- [Query Optimization](#query-optimization) -- [Index Strategy](#index-strategy) -- [Performance Monitoring](#performance-monitoring) -- [Connection Pool Management](#connection-pool-management) -- [Database Scaling Strategies](#database-scaling-strategies) -- [Backup and Recovery Optimization](#backup-and-recovery-optimization) -- [Security Hardening](#security-hardening) -- [Best Practices](#best-practices) - -## Overview - -The database optimization system provides comprehensive tools for: - -- **Query Performance Analysis** - Identify and optimize slow queries -- **Index Management** - Intelligent index creation and maintenance -- **Performance Monitoring** - Real-time metrics and alerting -- **Connection Pool Optimization** - Efficient connection management -- **Automated Optimization** - Self-tuning database configurations - -## Query Optimization - -### Query Analysis Service - -The `QueryOptimizerService` provides comprehensive query analysis and optimization: - -```typescript -// Analyze a query -const analysis = queryOptimizer.analyzeQuery( - 'SELECT * FROM users WHERE email = $1', - ['user@example.com'] -); - -console.log(analysis); -// { -// query: 'SELECT * FROM users WHERE email = $1', -// complexity: 2, -// recommendations: ['Add index on email column'], -// indexes: [{ column: 'email', type: 'btree', priority: 'high' }], -// optimizations: ['Consider selecting only needed columns'] -// } -``` - -### Query Performance Tracking - -Track query execution times and identify performance bottlenecks: - -```typescript -// Track query performance -queryOptimizer.trackQuery( - 'SELECT * FROM properties WHERE price > $1', - 150, // execution time in ms - 25 // row count -); - -// Get slow queries -const slowQueries = queryOptimizer.getSlowQueries(); - -// Get performance report -const report = queryOptimizer.generateOptimizationReport(); -``` - -### Query Optimization Features - -- **Automatic Query Analysis** - Complexity scoring and optimization suggestions -- **Slow Query Detection** - Configurable thresholds for slow query alerts -- **Index Recommendations** - AI-powered index suggestions based on query patterns -- **Performance Metrics** - Comprehensive query performance statistics -- **Optimization Reports** - Detailed reports with actionable recommendations - -## Index Strategy - -### Index Analysis Service - -The `IndexStrategyService` provides intelligent index management: - -```typescript -// Analyze table indexes -const analysis = indexStrategy.analyzeTableIndexes('users', { - rowCount: 1000000, - avgRowSize: 1024, - indexes: [ - { name: 'users_pkey', columns: ['id'], type: 'btree', usageCount: 50000 }, - { name: 'users_email_idx', columns: ['email'], type: 'btree', usageCount: 1000 } - ] -}); - -console.log(analysis.suggestions); -// [ -// { -// columns: ['created_at'], -// type: 'btree', -// reason: 'Frequently used in WHERE clause', -// priority: 'high' -// } -// ] -``` - -### Index Optimization - -Generate and execute index optimization plans: - -```typescript -// Generate optimization plan -const plan = indexStrategy.generateOptimizationPlan([analysis]); - -console.log(plan.createIndexes); -// [ -// { -// tableName: 'users', -// columns: ['created_at'], -// type: 'btree', -// sql: 'CREATE INDEX idx_users_created_at ON users (created_at);', -// estimatedBenefit: 85, -// estimatedTime: 2000 -// } -// ] -``` - -### Index Management Features - -- **Automatic Index Suggestions** - Based on query patterns and usage statistics -- **Unused Index Detection** - Identify and recommend removal of unused indexes -- **Duplicate Index Detection** - Find redundant or overlapping indexes -- **Size Estimation** - Estimate index size and growth -- **Partial Index Support** - Optimize with filtered indexes - -## Performance Monitoring - -### Real-time Monitoring - -The `PerformanceMonitorService` provides comprehensive performance monitoring: - -```typescript -// Get current metrics -const metrics = performanceMonitor.getMetrics(); - -console.log(metrics); -// { -// connections: 15, -// activeConnections: 8, -// totalQueries: 10000, -// slowQueries: 50, -// avgResponseTime: 120, -// cacheHitRate: 0.95 -// } -``` - -### Health Scoring - -Get overall database health score: - -```typescript -const healthScore = performanceMonitor.getHealthScore(); - -console.log(healthScore); -// { -// score: 85, -// status: 'excellent', -// issues: [] -// } -``` - -### Performance Alerts - -Set up real-time performance alerts: - -```typescript -performanceMonitor.on('alert', (alert) => { - console.log(`Alert: ${alert.message}`); - // Handle alert (send notification, log, etc.) -}); - -// Alert types: -// - SLOW_QUERY -// - HIGH_CONNECTION_UTILIZATION -// - HIGH_RESPONSE_TIME -// - LOW_CACHE_HIT_RATE -// - POOR_PERFORMANCE -``` - -### Monitoring Features - -- **Real-time Metrics** - Connection usage, query performance, cache efficiency -- **Health Scoring** - Overall database health assessment -- **Alert System** - Configurable thresholds and notifications -- **Performance Reports** - Detailed performance analysis -- **Trend Analysis** - Historical performance trends - -## Connection Pool Management - -### Connection Pool Service - -The `ConnectionPoolService` provides intelligent connection pool management: - -```typescript -// Get connection from pool -const connection = await connectionPool.getConnection(); - -// Use connection for database operations -try { - const result = await connection.query('SELECT * FROM users'); - return result.rows; -} finally { - // Release connection back to pool - await connectionPool.releaseConnection(connection); -} -``` - -### Pool Optimization - -Automatic pool optimization based on usage patterns: - -```typescript -// Optimize pool configuration -const optimization = await connectionPool.optimizePool(); - -console.log(optimization); -// { -// optimized: true, -// optimizations: ['Increased max connections to 15'], -// previousConfig: { min: 2, max: 10 }, -// newConfig: { min: 3, max: 15 } -// } -``` - -### Pool Monitoring - -Monitor pool status and performance: - -```typescript -const status = connectionPool.getPoolStatus(); - -console.log(status); -// { -// status: 'healthy', -// utilization: 0.6, -// errorRate: 0.01, -// avgWaitTime: 45, -// totalConnections: 10, -// activeConnections: 6 -// } -``` - -### Pool Management Features - -- **Dynamic Sizing** - Automatic pool size adjustment based on load -- **Connection Monitoring** - Track connection usage and wait times -- **Health Checks** - Validate connection health and performance -- **Timeout Management** - Configurable timeouts for different operations -- **Error Handling** - Robust error handling and recovery - -## Database Scaling Strategies - -### Horizontal Scaling - -#### Read Replicas - -```typescript -// Configure read replicas -const readReplicas = [ - { host: 'replica1.db.example.com', port: 5432 }, - { host: 'replica2.db.example.com', port: 5432 } -]; - -// Route read queries to replicas -const result = await queryRouter.execute('SELECT * FROM users', { - useReplica: true, - replicaStrategy: 'round-robin' -}); -``` - -#### Sharding Strategy - -```typescript -// Configure sharding -const shardingConfig = { - strategy: 'hash', - shardKey: 'user_id', - shards: [ - { host: 'shard1.db.example.com', range: [0, 1000000] }, - { host: 'shard2.db.example.com', range: [1000001, 2000000] } - ] -}; - -// Route queries to appropriate shard -const result = await shardRouter.execute('SELECT * FROM users WHERE user_id = $1', [1234567]); -``` - -### Vertical Scaling - -#### Resource Optimization - -```typescript -// Monitor resource usage -const resourceMetrics = await resourceMonitor.getMetrics(); - -// Auto-scale based on load -if (resourceMetrics.cpu > 0.8) { - await scalingManager.scaleUp('database'); -} -``` - -## Backup and Recovery Optimization - -### Optimized Backups - -```typescript -// Create optimized backup -const backupConfig = { - compression: true, - parallel: true, - incremental: true, - excludeTables: ['temp_sessions', 'cache_data'] -}; - -const backup = await backupManager.create(backupConfig); -``` - -### Point-in-Time Recovery - -```typescript -// Restore to specific point in time -const recovery = await recoveryManager.restore({ - timestamp: new Date('2024-01-15T10:30:00Z'), - excludeTables: ['audit_logs'], - validate: true -}); -``` - -## Security Hardening - -### Connection Security - -```typescript -// Configure secure connections -const securityConfig = { - ssl: true, - sslMode: 'require', - cert: '/path/to/client-cert.pem', - key: '/path/to/client-key.pem', - ca: '/path/to/ca-cert.pem' -}; - -await connectionPool.configure(securityConfig); -``` - -### Query Security - -```typescript -// Validate queries for security issues -const securityCheck = await securityValidator.validate(query); - -if (securityCheck.riskLevel === 'high') { - throw new Error('Query contains potential security risks'); -} -``` - -## Best Practices - -### 1. Query Optimization - -- **Use Specific Columns**: Avoid `SELECT *` queries -- **Add Appropriate Indexes**: Based on query patterns -- **Limit Result Sets**: Use `LIMIT` to prevent large result sets -- **Use Prepared Statements**: Prevent SQL injection and improve performance -- **Monitor Slow Queries**: Regularly review and optimize slow queries - -### 2. Index Management - -- **Regular Review**: Periodically review index usage -- **Remove Unused Indexes**: Delete indexes that aren't being used -- **Consider Partial Indexes**: For filtered data -- **Monitor Index Size**: Track index growth and impact -- **Use Composite Indexes**: For multi-column queries - -### 3. Connection Management - -- **Appropriate Pool Size**: Configure based on application load -- **Timeout Configuration**: Set reasonable timeouts -- **Connection Validation**: Validate connections before use -- **Monitor Pool Metrics**: Track pool performance -- **Handle Connection Errors**: Implement proper error handling - -### 4. Performance Monitoring - -- **Set Up Alerts**: Configure performance alerts -- **Regular Reports**: Generate performance reports -- **Monitor Trends**: Track performance over time -- **Baseline Metrics**: Establish performance baselines -- **Proactive Optimization**: Address issues before they impact users - -### 5. Security Practices - -- **Use SSL/TLS**: Encrypt database connections -- **Principle of Least Privilege**: Limit database user permissions -- **Regular Audits**: Audit database access and changes -- **Parameterized Queries**: Prevent SQL injection -- **Data Encryption**: Encrypt sensitive data at rest - -## Configuration - -### Environment Variables - -```bash -# Query Optimization -SLOW_QUERY_THRESHOLD=1000 -QUERY_CACHE_SIZE=100MB - -# Connection Pool -DB_POOL_MIN=2 -DB_POOL_MAX=10 -DB_POOL_ACQUIRE_TIMEOUT=30000 - -# Performance Monitoring -PERFORMANCE_MONITORING_INTERVAL=60000 -ALERT_THRESHOLDS_CONNECTION_UTILIZATION=0.8 -ALERT_THRESHOLDS_RESPONSE_TIME=500 - -# Index Strategy -AUTO_INDEX_CREATION=true -INDEX_USAGE_THRESHOLD=0.1 -``` - -### Service Configuration - -```typescript -// app.module.ts -import { DatabaseOptimizationModule } from './database/optimization'; - -@Module({ - imports: [ - DatabaseOptimizationModule.forRoot({ - slowQueryThreshold: 1000, - enableAutoOptimization: true, - monitoringInterval: 60000, - }) - ], -}) -export class AppModule {} -``` - -## Troubleshooting - -### Common Issues - -1. **High Connection Utilization** - - Increase pool size - - Optimize connection usage - - Check for connection leaks - -2. **Slow Query Performance** - - Add missing indexes - - Optimize query structure - - Check for table locks - -3. **Low Cache Hit Rate** - - Optimize cache configuration - - Review query patterns - - Increase cache size - -4. **High Memory Usage** - - Optimize result set sizes - - Implement pagination - - Review index usage - -### Diagnostic Tools - -```typescript -// Generate diagnostic report -const diagnostic = await diagnosticService.generateReport(); - -console.log(diagnostic); -// { -// overallHealth: 'good', -// issues: [ -// 'High connection utilization detected', -// 'Several unused indexes found' -// ], -// recommendations: [ -// 'Increase connection pool size', -// 'Remove unused indexes' -// ] -// } -``` - -## Conclusion - -The database optimization system provides comprehensive tools for maintaining optimal database performance. By implementing these strategies and regularly monitoring performance metrics, you can ensure your database remains efficient, scalable, and reliable. - -For questions or contributions to the optimization system, please refer to the development team or create an issue in the project repository. diff --git a/docs/DATABASE_SCHEMA.md b/docs/DATABASE_SCHEMA.md deleted file mode 100644 index d0ae6dbc..00000000 --- a/docs/DATABASE_SCHEMA.md +++ /dev/null @@ -1,365 +0,0 @@ -## Scaling Strategies - -### Vertical Scaling - -- Increase CPU, RAM, and disk IOPS on the PostgreSQL server for higher throughput. -- Adjust `connection_limit` in the DATABASE_URL to match available resources. - -### Horizontal Scaling - -- Use read replicas for scaling read-heavy workloads. Configure Prisma to use replicas for read queries (future enhancement). -- For global scale, consider managed PostgreSQL services (e.g., AWS RDS, GCP Cloud SQL) with multi-region support. - -### Connection Pool Tuning - -- Tune `connection_limit` and `pool_timeout` in the DATABASE_URL for optimal pool size. -- Monitor active connections and adjust pool size as needed. - -### Caching - -- Use Redis for caching frequently accessed data and query results. -- Cache count queries and first-page results for large datasets. - -### Partitioning and Sharding (Advanced) - -- For very large tables, consider PostgreSQL table partitioning. -- Sharding is not natively supported by Prisma, but can be implemented at the application layer if needed. - -### High Availability & Failover - -- Use managed PostgreSQL with automatic failover and backups. -- Regularly test backup and restore procedures (see backup.sh and restore.sh). - -### Monitoring - -- Monitor query performance and slow queries using Prisma logs and PostgreSQL tools (pg_stat_statements). -- Set up external monitoring (e.g., Prometheus, Grafana) for database metrics. - -// See SETUP.md for more performance and monitoring tips. - -# PropChain Database Schema Documentation - -## Overview - -This document describes the complete PostgreSQL database schema for PropChain, including all entities, relationships, constraints, and indexes. - -## Technology Stack - -- **Database**: PostgreSQL 15+ -- **ORM**: Prisma 5.x -- **Connection Pooling**: Prisma connection pool (configured via DATABASE_URL) - -## Entity Relationship Diagram - -``` -┌─────────────┐ ┌─────────────────┐ ┌───────────────┐ -│ User │───────│ Property │───────│ Transaction │ -└─────────────┘ └─────────────────┘ └───────────────┘ - │ │ │ - │ │ │ - ▼ ▼ ▼ -┌─────────────┐ ┌─────────────────┐ ┌───────────────┐ -│ Role │ │ Document │◄──────│ Document │ -└─────────────┘ └─────────────────┘ └───────────────┘ - │ - ▼ -┌─────────────┐ ┌─────────────────┐ -│ Permission │◄──────│ RolePermission │ -└─────────────┘ └─────────────────┘ -``` - -## Models - -### User - -Primary user entity representing all platform participants. - -| Field | Type | Constraints | Description | -| ------------- | -------- | ----------------- | ------------------------ | -| id | String | Primary Key, CUID | Unique identifier | -| email | String | Unique, Not Null | User email address | -| walletAddress | String | Unique, Nullable | Ethereum wallet address | -| role | UserRole | Not Null, Default | User role enum | -| roleId | String | Foreign Key | Reference to Role entity | -| createdAt | DateTime | Default: now() | Creation timestamp | -| updatedAt | DateTime | Auto-updated | Last update timestamp | - -**Indexes**: `email`, `walletAddress`, `role`, `createdAt` - -**Relations**: - -- One-to-Many: Properties (as owner) -- One-to-Many: Transactions (as recipient via walletAddress) -- One-to-Many: Documents (as uploader) -- Many-to-One: Role -- One-to-Many: RoleChangeLog - -### Property - -Real estate property listings. - -| Field | Type | Constraints | Description | -| ----------- | -------------- | ----------------- | ------------------------- | -| id | String | Primary Key, CUID | Unique identifier | -| title | String | Not Null | Property title | -| description | String | Nullable | Property description | -| location | String | Not Null | Property address/location | -| price | Decimal | Not Null | Property price | -| status | PropertyStatus | Not Null, Default | Listing status | -| ownerId | String | Foreign Key | Reference to User (owner) | -| createdAt | DateTime | Default: now() | Creation timestamp | -| updatedAt | DateTime | Auto-updated | Last update timestamp | - -**Indexes**: `ownerId`, `status`, `createdAt`, `location` - -**Relations**: - -- Many-to-One: User (owner) - CASCADE delete -- One-to-Many: Transactions -- One-to-Many: Documents - -### Transaction - -Blockchain transactions for property purchases and transfers. - -| Field | Type | Constraints | Description | -| ----------- | ----------------- | --------------------- | --------------------------- | -| id | String | Primary Key, CUID | Unique identifier | -| fromAddress | String | Not Null | Sender wallet address | -| toAddress | String | Not Null | Recipient wallet address | -| amount | Decimal | Not Null | Transaction amount | -| txHash | String | Nullable | Blockchain transaction hash | -| status | TransactionStatus | Not Null, Default | Transaction status | -| type | TransactionType | Not Null | Transaction type | -| propertyId | String | Foreign Key, Nullable | Reference to Property | -| createdAt | DateTime | Default: now() | Creation timestamp | -| updatedAt | DateTime | Auto-updated | Last update timestamp | - -**Indexes**: `fromAddress`, `toAddress`, `status`, `createdAt`, `propertyId` - -**Relations**: - -- Many-to-One: Property - SET NULL on delete -- Many-to-One: User (recipient via walletAddress) -- One-to-Many: Documents - -### Document - -Document storage for property verification and transactions. - -| Field | Type | Constraints | Description | -| ------------- | -------------- | --------------------- | ----------------------------- | -| id | String | Primary Key, CUID | Unique identifier | -| name | String | Not Null | Document name | -| type | DocumentType | Not Null | Document type enum | -| status | DocumentStatus | Not Null, Default | Verification status | -| fileUrl | String | Not Null | Storage URL | -| fileHash | String | Nullable | Content hash for verification | -| mimeType | String | Nullable | File MIME type | -| fileSize | Int | Nullable | File size in bytes | -| description | String | Nullable | Document description | -| propertyId | String | Foreign Key, Nullable | Reference to Property | -| transactionId | String | Foreign Key, Nullable | Reference to Transaction | -| uploadedById | String | Foreign Key | Reference to User (uploader) | -| verifiedAt | DateTime | Nullable | Verification timestamp | -| expiresAt | DateTime | Nullable | Expiration date | -| createdAt | DateTime | Default: now() | Creation timestamp | -| updatedAt | DateTime | Auto-updated | Last update timestamp | - -**Indexes**: `propertyId`, `transactionId`, `uploadedById`, `type`, `status`, `createdAt` - -**Relations**: - -- Many-to-One: Property - SET NULL on delete -- Many-to-One: Transaction - SET NULL on delete -- Many-to-One: User (uploader) - CASCADE delete - -### Role - -RBAC role definitions. - -| Field | Type | Constraints | Description | -| ----------- | -------- | ----------------- | ------------------------ | -| id | String | Primary Key, CUID | Unique identifier | -| name | String | Unique, Not Null | Role name | -| description | String | Nullable | Role description | -| level | Int | Default: 0 | Role hierarchy level | -| isSystem | Boolean | Default: false | System-defined role flag | -| createdAt | DateTime | Default: now() | Creation timestamp | -| updatedAt | DateTime | Auto-updated | Last update timestamp | - -**Relations**: - -- One-to-Many: Users -- One-to-Many: RolePermissions -- One-to-Many: RoleChangeLog - -### Permission - -Granular permission definitions. - -| Field | Type | Constraints | Description | -| ----------- | -------- | ----------------- | ---------------------- | -| id | String | Primary Key, CUID | Unique identifier | -| resource | String | Not Null | Resource name | -| action | String | Not Null | Action name (CRUD) | -| description | String | Nullable | Permission description | -| createdAt | DateTime | Default: now() | Creation timestamp | -| updatedAt | DateTime | Auto-updated | Last update timestamp | - -**Unique Constraint**: `[resource, action]` - -**Relations**: - -- One-to-Many: RolePermissions - -### ApiKey - -API key management for external integrations. - -| Field | Type | Constraints | Description | -| ------------ | -------- | ----------------- | ----------------------------- | -| id | String | Primary Key, CUID | Unique identifier | -| name | String | Not Null | Key name/description | -| key | String | Unique, Not Null | Hashed API key | -| keyPrefix | String | Not Null | Key prefix for identification | -| scopes | String[] | Not Null | Allowed scopes | -| requestCount | BigInt | Default: 0 | Total request count | -| lastUsedAt | DateTime | Nullable | Last usage timestamp | -| isActive | Boolean | Default: true | Active status | -| rateLimit | Int | Nullable | Requests per minute limit | -| createdAt | DateTime | Default: now() | Creation timestamp | -| updatedAt | DateTime | Auto-updated | Last update timestamp | - -**Indexes**: `keyPrefix`, `isActive`, `createdAt` - -## Enums - -### UserRole - -- `ADMIN` - Full system access -- `AGENT` - Property management -- `SELLER` - Can list properties -- `BUYER` - Can purchase properties -- `VIEWER` - Read-only access -- `USER` - Standard user -- `VERIFIED_USER` - Verified standard user - -### PropertyStatus - -- `DRAFT` - Not yet submitted -- `PENDING` - Awaiting approval -- `APPROVED` - Approved for listing -- `LISTED` - Currently listed -- `SOLD` - Property sold -- `REMOVED` - Removed from listing - -### TransactionStatus - -- `PENDING` - Awaiting processing -- `PROCESSING` - Currently processing -- `COMPLETED` - Successfully completed -- `FAILED` - Transaction failed -- `CANCELLED` - Transaction cancelled - -### TransactionType - -- `PURCHASE` - Property purchase -- `TRANSFER` - Property transfer -- `ESCROW` - Escrow deposit -- `REFUND` - Refund transaction - -### DocumentType - -- `TITLE_DEED` - Property title deed -- `OWNERSHIP_CERTIFICATE` - Ownership certificate -- `INSPECTION_REPORT` - Property inspection -- `APPRAISAL` - Property appraisal -- `INSURANCE` - Insurance documents -- `TAX_DOCUMENT` - Tax-related documents -- `CONTRACT` - Contracts and agreements -- `IDENTITY` - Identity verification -- `OTHER` - Other documents - -### DocumentStatus - -- `PENDING` - Awaiting verification -- `VERIFIED` - Verified and valid -- `REJECTED` - Rejected/invalid -- `EXPIRED` - Document expired - -## Database Configuration - -### Connection String Format - -``` -postgresql://[user]:[password]@[host]:[port]/[database]?connection_limit=10&pool_timeout=30 -``` - -### Connection Pooling Parameters - -- `connection_limit` - Maximum number of connections (default: 10) -- `pool_timeout` - Connection pool timeout in seconds (default: 30) - -### Recommended Production Settings - -```env -DATABASE_URL="postgresql://postgres:password@localhost:5432/propchain?connection_limit=20&pool_timeout=30&statement_cache_size=100" -``` - -## Migrations - -### Running Migrations - -```bash -# Development -npm run migrate - -# Production -npm run migrate:deploy - -# Reset database (development only) -npm run migrate:reset -``` - -### Creating New Migrations - -```bash -npx prisma migrate dev --name -``` - -## Seeding - -### Run Seed Data - -```bash -npm run db:seed -``` - -The seed script creates: - -- System roles (Administrator, Agent, User) -- Default permissions for each role -- Sample users (admin, agent, buyer, seller) -- Sample properties -- Sample transactions -- Sample documents -- Development API keys - -## Performance Considerations - -### Index Strategy - -All foreign keys and frequently queried fields are indexed. The following query patterns are optimized: - -- User lookup by email/wallet -- Property search by owner, status, location -- Transaction lookup by addresses, status, property -- Document retrieval by property, transaction, uploader - -### Query Optimization Tips - -1. Use `select` to limit returned fields -2. Use `include` sparingly - prefer explicit joins -3. Use pagination for large result sets -4. Use transactions for related operations diff --git a/docs/DEVELOPER_GUIDE.md b/docs/DEVELOPER_GUIDE.md deleted file mode 100644 index 83d486fd..00000000 --- a/docs/DEVELOPER_GUIDE.md +++ /dev/null @@ -1,134 +0,0 @@ -# PropChain Backend Developer Guide - -Welcome to the PropChain Backend developer documentation. This guide provides a comprehensive overview of the project architecture, setup, and contribution guidelines. - -## Table of Contents - -- [Project Overview](#project-overview) -- [Architecture](#architecture) -- [Getting Started](#getting-started) -- [Development Workflow](#development-workflow) -- [Module Organization](#module-organization) -- [Service Layer Architecture](./SERVICE_LAYER_ARCHITECTURE.md) -- [Database & Prisma](#database--prisma) -- [Security](#security) -- [Testing](#testing) -- [Documentation](#documentation) - -## Project Overview - -PropChain is a decentralized real estate infrastructure. The backend provides a blockchain-powered API for property transactions, valuation, and user management. - -**Core Technologies:** -- **Framework:** NestJS (Node.js) -- **Language:** TypeScript -- **Database:** PostgreSQL (via Prisma ORM) -- **Cache:** Redis -- **Blockchain:** Ethereum/EVM (via Hardhat/Ethers.js) -- **API Documentation:** Swagger (OpenAPI 3.0) - -## Architecture - -The project follows a modular architecture based on NestJS principles. Each feature is encapsulated within its own module. - -### Core Modules -- **Auth:** Handles authentication (JWT, Web3 login) and authorization (RBAC). -- **Users:** Manages user profiles, activity, and relationships. -- **Properties:** Core logic for property management and transactions. -- **Database:** Prisma integration and migration utilities. -- **Common:** Shared utilities, logging, and error handling. - -For more details on internal organization, see the [Module Organization Guide](./MODULE_ORGANIZATION_GUIDE.md) and the [Service Layer Architecture](./SERVICE_LAYER_ARCHITECTURE.md). - -## Getting Started - -### Prerequisites -- Node.js >= 18.0.0 -- PostgreSQL -- Redis -- Docker (optional, but recommended) - -### Setup -1. Clone the repository -2. Install dependencies: `npm install` -3. Configure environment: `cp .env.example .env` (Update with your local settings) -4. Initialize database: `npm run db:reset` -5. Start in development mode: `npm run start:dev` - -See [ENVIRONMENT_VARIABLES.md](./ENVIRONMENT_VARIABLES.md) for detailed configuration options. - -## Development Workflow - -### Coding Standards -- Follow the [Module Organization Guide](./MODULE_ORGANIZATION_GUIDE.md) for file structure and naming. -- Follow the [Service Layer Architecture](./SERVICE_LAYER_ARCHITECTURE.md) guide for boundary validation and dependency injection patterns. -- Use JSDoc for all public classes and methods. -- Run linting before committing: `npm run lint` - -### Git Commit Conventions -We use conventional commits. Huskey and lint-staged are configured to enforce these standards. -- `feat:` New features -- `fix:` Bug fixes -- `docs:` Documentation changes -- `chore:` Maintenance tasks - -## Database & Prisma - -We use Prisma as our ORM. Always use `prisma/schema.prisma` as the single source of truth for your data models. - -**Common Commands:** -- `npm run db:generate`: Regenerate Prisma client -- `npm run migrate`: Create and apply a new migration -- `npm run db:seed`: Seed the database with initial data - -See the [DATABASE_SCHEMA.md](./DATABASE_SCHEMA.md), [DATABASE_OPTIMIZATION_GUIDE.md](./DATABASE_OPTIMIZATION_GUIDE.md), and [ZERO_DOWNTIME_MIGRATIONS.md](./ZERO_DOWNTIME_MIGRATIONS.md) for more info. - -## Security - -Security is integrated at multiple levels: -- **JWT Hardening:** Advanced validation and token rotation. -- **RBAC:** Fine-grained role-based access control. -- **Threat Detection:** Automatic blocking of suspicious activity. -- **Input Sanitization:** Interceptors to prevent SQL injection and XSS. - -Refer to the [API_SECURITY_GUIDE.md](./API_SECURITY_GUIDE.md) for implementation details. - -## Testing - -We prioritize high test coverage across different layers: -- **Unit Tests (`*.spec.ts`):** Focus on individual class logic. -- **Integration Tests:** Focus on module interactions. -- **E2E Tests:** Full request/response flow validation. - -**Run Tests:** -- `npm run test`: Run all tests -- `npm run test:cov`: Generate coverage report - -## CI/CD Pipeline - -The project uses an optimized GitHub Actions pipeline for continuous integration and deployment. - -### Key Features: -- **Parallel Execution:** Linting, Unit Tests, Integration Tests, E2E Tests, and Security Tests run in parallel to minimize feedback time. -- **Caching:** Dependency caching via `actions/setup-node` and Prisma client caching to speed up subsequent runs. -- **Environment Separation:** Automated deployment stages for `Staging` (on `develop` and `main` push) and `Production` (on `main` push). -- **Build Artifacts:** The production build is generated once and reused across deployment stages to ensure consistency. - -### Deployment Strategy: -- **Staging:** Automatic deployment to the staging environment for verification. -- **Production:** Continuous deployment to production with environment-specific protections and manual approval gates (if configured in GitHub). - -## Documentation - -### Automated API Docs (Swagger) -The API is documented using Swagger. Access it at `/api/docs` when the server is running. -Ensure DTOs are properly decorated with `@ApiProperty`. - -### Automated Developer Docs (TypeDoc) -We use TypeDoc to generate detailed developer documentation from JSDoc comments. -- **Generate Docs:** `npm run docs:generate` -- **Output:** `docs/developer/auto-generated/` - ---- - -*Generated by PropChain Team* diff --git a/docs/EMAIL_COMMUNICATION_GUIDE.md b/docs/EMAIL_COMMUNICATION_GUIDE.md deleted file mode 100644 index 78d95b5c..00000000 --- a/docs/EMAIL_COMMUNICATION_GUIDE.md +++ /dev/null @@ -1,534 +0,0 @@ -# Email and Communication System Guide - -This guide covers the comprehensive email and communication system implemented in the PropChain Backend project, providing advanced features for multi-channel communication, automation, and deliverability optimization. - -## Table of Contents - -- [Overview](#overview) -- [Email Template System](#email-template-system) -- [Email Automation and Workflows](#email-automation-and-workflows) -- [Multi-Channel Communication](#multi-channel-communication) -- [Email Analytics and Tracking](#email-analytics-and-tracking) -- [Email Scheduling and Batch Processing](#email-scheduling-and-batch-processing) -- [Email Personalization and A/B Testing](#email-personalization-and-ab-testing) -- [Email Preference Management](#email-preference-management) -- [Email Deliverability Optimization](#email-deliverability-optimization) -- [Configuration](#configuration) -- [Best Practices](#best-practices) - -## Overview - -The communication system provides enterprise-grade email and multi-channel communication capabilities with: - -- **Dynamic Email Templates** - Personalized content with conditional logic -- **Advanced Automation** - Workflow-based triggers and actions -- **Multi-Channel Support** - Email, SMS, Push, In-App, Webhook -- **Comprehensive Analytics** - Real-time tracking and performance metrics -- **Intelligent Scheduling** - Batch processing and timed delivery -- **A/B Testing** - Automated testing and optimization -- **Preference Management** - User-controlled communication preferences -- **Deliverability Optimization** - Sender reputation and inbox placement - -## Email Template System - -### Template Rendering - -The `EmailTemplateService` provides powerful template rendering with: - -```typescript -// Basic template rendering -const rendered = templateService.renderTemplate('welcome', { - firstName: 'John', - verificationUrl: 'https://app.propchain.com/verify/abc123' -}); - -// A/B testing variant -const variant = templateService.createABTestVariant('welcome', 'A', { - subject: 'Welcome to PropChain, John! 🎉' -}); - -// Template preview -const preview = templateService.previewTemplate('welcome', data); -``` - -### Template Features - -- **Dynamic Content** - Variable substitution with dot notation -- **Conditional Blocks** - `{{#if condition}}...{{/if}}` -- **Loop Blocks** - `{{#each items}}...{{/each}}` -- **Localization** - Multi-language template support -- **A/B Testing** - Built-in variant creation -- **Preview Mode** - Test templates with sample data - -### Template Types - -- **Welcome Emails** - User onboarding and verification -- **Transaction Emails** - Password resets, notifications, alerts -- **Marketing Emails** - Newsletters, promotions, announcements -- **Security Emails** - Login alerts, suspicious activity warnings - -## Email Automation and Workflows - -### Workflow Engine - -The `WorkflowService` enables complex automated communication: - -```typescript -// Create custom workflow -const workflow = await workflowService.createWorkflow({ - name: 'Cart Recovery', - description: 'Recover abandoned shopping carts', - steps: [ - { - id: 'check_cart', - type: 'condition', - config: { condition: 'context.event.data.cartValue > 50' } - }, - { - id: 'send_recovery_email', - type: 'send_email', - config: { templateName: 'cart_recovery' } - } - ] -}); - -// Execute workflow -const result = await workflowService.executeWorkflow('cart_recovery', { - userId: 'user_123', - trigger: 'cart_abandoned', - event: { - type: 'cart_abandoned', - data: { cartValue: 75, items: 3 } - } -}); -``` - -### Workflow Capabilities - -- **Trigger System** - Event-based workflow initiation -- **Step Types** - Email, SMS, Push, Delay, Condition, Webhook, Script -- **Conditional Logic** - Complex decision trees and branching -- **Error Handling** - Step-level failure handling and retry logic -- **Scheduling** - Time-based and recurring workflow execution - -### Built-in Workflows - -- **Welcome Series** - Multi-step onboarding sequence -- **Cart Recovery** - Abandoned cart email series -- **Re-engagement** - Inactive user reactivation campaigns -- **Security Alerts** - Suspicious activity notifications - -## Multi-Channel Communication - -### Channel Support - -The `MultichannelService` provides unified communication across: - -```typescript -// Send via multiple channels -const result = await multichannelService.sendMultichannel( - 'user_123', - { - subject: 'Security Alert', - content: 'New login detected from new device', - priority: 'high' - }, - ['email', 'sms', 'push'], - { - email: { priority: 'high' }, - sms: { priority: 'high' }, - push: { priority: 'normal' } - } -); - -// Channel-specific sending -await multichannelService.sendSMS('+1234567890', 'Your verification code is 123456'); -await multichannelService.sendPushNotification('user_123', { - title: 'New Message', - body: 'You have a new notification' -}); -``` - -### Supported Channels - -- **Email** - Rich HTML templates with tracking -- **SMS** - Transactional and marketing messages -- **Push Notifications** - Mobile app notifications with actions -- **In-App** - Real-time application notifications -- **Webhook** - HTTP callbacks to external systems -- **Slack/Discord** - Team communication integrations - -### Channel Features - -- **Fallback Logic** - Automatic channel switching on failure -- **Rate Limiting** - Per-channel throttling -- **Personalization** - Channel-specific content adaptation -- **Analytics** - Unified tracking across all channels - -## Email Analytics and Tracking - -### Real-time Analytics - -The `EmailAnalyticsService` provides comprehensive tracking: - -```typescript -// Track email events -await analyticsService.trackEmailSent({ - emailId: 'email_123', - templateName: 'welcome', - recipientCount: 1, - provider: 'smtp', - deliveryTime: 1200, - success: true -}); - -// Get template performance -const performance = await analyticsService.getTemplatePerformance('welcome', { - start: new Date('2024-01-01'), - end: new Date('2024-01-31') -}); - -// A/B test results -const abTest = await analyticsService.getABTestResults('welcome_test_2024'); -``` - -### Analytics Features - -- **Delivery Tracking** - Sent, delivered, bounced, complained -- **Engagement Tracking** - Opens, clicks, read status -- **Performance Metrics** - Delivery rates, open rates, click-through rates -- **A/B Testing** - Statistical significance and winner determination -- **Real-time Monitoring** - Live dashboards and alerts - -### Tracking Implementation - -- **Tracking Pixels** - Automatic open tracking pixel insertion -- **Tracking Links** - Click tracking with link IDs -- **Webhook Events** - Real-time delivery status updates -- **Bounce Processing** - Automated bounce handling and list cleaning - -## Email Scheduling and Batch Processing - -### Advanced Queue System - -The `EmailQueueService` provides enterprise-grade queuing: - -```typescript -// Schedule email for later -const jobId = await queueService.addScheduled(emailData, new Date('2024-01-15 09:00')); - -// Batch email processing -const batchResult = await queueService.addBatch([ - { data: email1, metadata: { campaignId: 'campaign_1' } }, - { data: email2, metadata: { campaignId: 'campaign_1' } }, - { data: email3, metadata: { campaignId: 'campaign_1' } } -], { - rateLimit: 1000, // 1 second between emails - maxConcurrency: 5 -}); - -// High priority email -await queueService.addHighPriority(securityAlert); -``` - -### Queue Features - -- **Priority Queues** - Separate queues for different priority levels -- **Rate Limiting** - Configurable throttling between sends -- **Retry Logic** - Exponential backoff with max attempts -- **Batch Processing** - Efficient bulk email handling -- **Monitoring** - Real-time queue statistics and health - -### Scheduling Capabilities - -- **Time Zone Support** - User-localized scheduling -- **Recurring Jobs** - Daily, weekly, monthly automated sends -- **Optimal Send Times** - AI-powered send time optimization -- **Volume Control** - Daily/hourly sending limits - -## Email Personalization and A/B Testing - -### Dynamic Personalization - -The system supports advanced personalization: - -```typescript -// Personalized email with rules -const result = await emailService.sendPersonalizedEmail( - 'user@example.com', - 'welcome', - baseData, - [ - { - condition: 'data.userType === "premium"', - transformation: { - type: 'set', - field: 'premiumFeatures', - value: 'Get premium support and exclusive features!' - } - } - ] -); -``` - -### A/B Testing Framework - -- **Automated Testing** - Split traffic between variants -- **Statistical Analysis** - Confidence intervals and significance testing -- **Winner Selection** - Automatic winner determination -- **Traffic Allocation** - Configurable percentage splits -- **Test Duration** - Time-based or conversion-based test ending - -### Personalization Features - -- **Conditional Content** - Rules-based content variation -- **Dynamic Variables** - User data integration -- **Behavioral Targeting** - Past interaction-based content -- **Demographic Segmentation** - Age, location, preference-based targeting - -## Email Preference Management - -### Comprehensive Preferences - -The `PreferenceService` provides full user control: - -```typescript -// Get user preferences -const preferences = await preferenceService.getUserPreferences('user_123'); - -// Update specific channel preferences -await preferenceService.updateEmailPreferences('user_123', { - marketing: false, - frequency: 'daily' -}); - -// Unsubscribe from specific type -await preferenceService.unsubscribe('user_123', 'email', 'marketing', 'token_abc123'); -``` - -### Preference Features - -- **Channel Control** - Enable/disable per communication channel -- **Content Types** - Marketing, transactional, security preferences -- **Frequency Control** - Immediate, hourly, daily, weekly delivery -- **Quiet Hours** - Do-not-disturb time windows -- **Bulk Operations** - Import/export preference management - -### Unsubscribe System - -- **Token-based Unsubscribes** - Secure, time-limited unsubscribe links -- **One-click Unsubscribes** - Easy opt-out for all communications -- **Preference Centers** - User-friendly preference management interface -- **Compliance Reporting** - CAN-SPAM compliance and audit trails - -## Email Deliverability Optimization - -### Sender Reputation Management - -The `DeliverabilityService` ensures maximum inbox placement: - -```typescript -// Analyze deliverability -const analysis = await deliverabilityService.analyzeDeliverability({ - emailId: 'email_123', - sender: 'noreply@propchain.com', - recipients: ['user@example.com'], - subject: 'Welcome to PropChain', - content: '

Welcome!

' -}); - -// IP warmup -const warmupResult = await deliverabilityService.warmupIP('192.168.1.100', { - name: 'Standard Warmup', - durationDays: 14, - dailyVolume: [10, 20, 40, 60, 100, 200, 300, 500, 800, 1000] -}); - -// Get recommendations -const recommendations = await deliverabilityService.getDeliverabilityRecommendations('noreply@propchain.com'); -``` - -### Deliverability Features - -- **Reputation Monitoring** - Real-time sender score tracking -- **Authentication Setup** - SPF, DKIM, DMARC configuration guidance -- **Content Optimization** - Spam trigger detection and avoidance -- **List Hygiene** - Automated email list cleaning and validation -- **IP Warmup** - Gradual IP reputation building -- **Inbox Placement** - Gmail, Outlook, Yahoo optimization - -### Optimization Tools - -- **Content Analysis** - Spam score calculation and improvement suggestions -- **Technical Audit** - DNS records, authentication setup verification -- **Performance Monitoring** - Delivery rates, bounce rates, complaint tracking -- **Recommendation Engine** - AI-powered optimization suggestions - -## Configuration - -### Environment Variables - -```bash -# Email Configuration -EMAIL_FROM=noreply@propchain.com -SMTP_HOST=smtp.gmail.com -SMTP_PORT=587 -SMTP_SECURE=false -SMTP_USER=your-email@gmail.com -SMTP_PASS=your-app-password - -# Multi-channel Configuration -TWILIO_ACCOUNT_SID=your_twilio_sid -TWILIO_AUTH_TOKEN=your_twilio_token -FIREBASE_SERVER_KEY=your_firebase_key - -# Queue Configuration -REDIS_HOST=localhost -REDIS_PORT=6379 -REDIS_PASSWORD=your_redis_password - -# Deliverability Configuration -DEFAULT_SENDER_EMAIL=noreply@propchain.com -PREFERENCE_EXPORT_SECRET=your_export_secret -BASE_URL=https://api.propchain.com -``` - -### Service Configuration - -```typescript -// app.module.ts -import { CommunicationModule } from './communication/communication.module'; - -@Module({ - imports: [ - CommunicationModule.forRoot({ - email: { - templates: { - path: './templates', - defaultLocale: 'en' - }, - providers: { - smtp: { - host: process.env.SMTP_HOST, - port: parseInt(process.env.SMTP_PORT || '587'), - secure: process.env.SMTP_SECURE === 'true' - } - } - }, - multichannel: { - providers: { - sms: 'twilio', - push: 'firebase' - } - }, - analytics: { - tracking: { - enabled: true, - pixelDomain: 'track.propchain.com' - } - } - }) - ], -}) -export class AppModule {} -``` - -## Best Practices - -### 1. Template Management - -- **Keep Templates Simple** - Avoid complex nested structures -- **Mobile-First Design** - Ensure templates work on all devices -- **Test Thoroughly** - Preview across email clients and devices -- **Use Semantic HTML** - Proper heading structure and accessibility -- **Include Plain Text** - Fallback for email clients that don't support HTML - -### 2. Personalization Strategies - -- **Use Real Data** - Leverage user behavior and preferences -- **Avoid Over-Personalization** - Don't be creepy with excessive personal data -- **Test Personalization Rules** - Ensure conditional logic works correctly -- **Respect Privacy** - Follow data protection regulations -- **Segment Appropriately** - Group users by behavior, not just demographics - -### 3. Deliverability Optimization - -- **Warm Up New IPs** - Gradually increase sending volume -- **Monitor Reputation** - Track sender scores across providers -- **Clean Lists Regularly** - Remove invalid addresses and complainers -- **Use Authentication** - Implement SPF, DKIM, and DMARC -- **Test Before Sending** - Use seed lists and spam checkers - -### 4. Analytics and Monitoring - -- **Track Key Metrics** - Monitor delivery, open, and click rates -- **Set Up Alerts** - Immediate notification of deliverability issues -- **Analyze A/B Tests** - Use statistical significance testing -- **Monitor Sender Health** - Track reputation across all sending domains -- **Use Real-time Dashboards** - Live monitoring of campaign performance - -### 5. Compliance and Legal - -- **Honor Unsubscribes** - Process opt-outs promptly -- **Include Physical Address** - When required by law -- **Provide Clear Privacy Policy** - Transparent data usage explanation -- **Follow CAN-SPAM Rules** - Include unsubscribe links and physical addresses -- **Maintain Audit Trails** - Log all consent and preference changes - -### 6. Performance Optimization - -- **Use Queue Systems** - Prevent overwhelming receiving servers -- **Implement Rate Limiting** - Respect provider and ISP limits -- **Optimize Send Times** - Schedule for optimal engagement -- **Monitor Queue Health** - Prevent bottlenecks and failures -- **Use Connection Pooling** - Efficient SMTP connection management - -## Troubleshooting - -### Common Issues - -1. **Low Delivery Rates** - - Check sender reputation - - Verify SPF/DKIM/DMARC records - - Clean email lists - - Reduce sending frequency - -2. **High Spam Complaints** - - Review content for spam triggers - - Ensure proper consent - - Check list acquisition methods - - Improve personalization relevance - -3. **Template Rendering Issues** - - Verify template syntax - - Check data variable availability - - Test with sample data - - Review conditional logic - -4. **Queue Bottlenecks** - - Monitor queue sizes - - Check worker counts - - Review processing times - - Scale horizontally if needed - -### Debug Tools - -```typescript -// Enable debug logging -const logger = new Logger('EmailService', { level: 'debug' }); - -// Test email configuration -const testResult = await emailService.testConfiguration(); - -// Preview templates -const preview = templateService.previewTemplate('welcome', testData); - -// Check queue status -const stats = await queueService.getAllQueueStats(); -``` - -## Conclusion - -The email and communication system provides enterprise-grade capabilities for managing all aspects of digital communication. With advanced templates, automation, multi-channel support, analytics, and deliverability optimization, it ensures reliable and effective communication with your users. - -For questions or contributions to the communication system, please refer to the development team or create an issue in the project repository. diff --git a/docs/ENVIRONMENT_VARIABLES.md b/docs/ENVIRONMENT_VARIABLES.md deleted file mode 100644 index 29b7e746..00000000 --- a/docs/ENVIRONMENT_VARIABLES.md +++ /dev/null @@ -1,158 +0,0 @@ -# Environment Variables Documentation - -This document describes all required environment variables for the PropChain Backend. - -## DATABASE_URL - -**Description:** PostgreSQL connection string - -**Type:** url - -**Required:** Yes - -**Example:** `postgresql://user:password@localhost:5432/propchain` - -## JWT_SECRET - -**Description:** JWT secret key (minimum 32 characters) - -**Type:** string - -**Required:** Yes - -**Example:** `your-secret-value` - -**Additional Validation:** Custom validation rules apply - -## JWT_REFRESH_SECRET - -**Description:** JWT refresh secret key (minimum 32 characters) - -**Type:** string - -**Required:** Yes - -**Example:** `your-secret-value` - -**Additional Validation:** Custom validation rules apply - -## ENCRYPTION_KEY - -**Description:** 32-character encryption key for AES-256 - -**Type:** string - -**Required:** Yes - -**Example:** `your-secret-value` - -**Additional Validation:** Custom validation rules apply - -## RPC_URL - -**Description:** Blockchain RPC endpoint URL - -**Type:** url - -**Required:** Yes - -**Example:** `https://example.com` - -## PRIVATE_KEY - -**Description:** Ethereum private key (0x followed by 64 hex characters) - -**Type:** private-key - -**Required:** Yes - -**Example:** `0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef` - -## SESSION_SECRET - -**Description:** Session secret key (minimum 32 characters) - -**Type:** string - -**Required:** Yes - -**Example:** `your-secret-value` - -**Additional Validation:** Custom validation rules apply - -## EMAIL_FROM - -**Description:** Default email address for sending emails - -**Type:** email - -**Required:** Yes - -**Example:** `noreply@example.com` - -## Security Guidelines - -### Production Environment -- Never use default or example values in production -- Ensure all secrets are at least 32 characters long -- Use environment-specific configuration files -- Rotate secrets regularly - -### Development Environment -- Use `.env.local` for local development overrides -- Keep sensitive values out of version control -- Use the provided templates as starting points - -## Validation Features - -The PropChain Backend includes comprehensive environment variable validation: - -- **Type Validation**: Ensures values match expected formats (URL, email, etc.) -- **Security Checks**: Detects common insecure patterns -- **Required Variable Checking**: Validates all required variables are present -- **Custom Validation**: Additional rules for sensitive values - -## Templates - -Environment-specific templates are available in the `docs/` directory: -- `.env.development.template` - Development configuration -- `.env.staging.template` - Staging configuration -- `.env.production.template` - Production configuration - -## Testing - -Run environment variable tests: - -```bash -npm run test:env -``` - -Test reports are generated in `test-reports/env-validation.md`. - -## Troubleshooting - -### Common Issues - -1. **Missing Required Variables** - - Check the validation error messages - - Ensure all required variables are set - - Use the provided templates as reference - -2. **Invalid Format** - - Verify URLs are properly formatted - - Check email addresses are valid - - Ensure Ethereum addresses and private keys follow correct format - -3. **Security Warnings** - - Replace default values with secure ones - - Avoid using development values in production - - Ensure secrets meet minimum length requirements - -### Validation Errors - -If validation fails on startup, the application will: -1. Display all validation errors -2. Exit with error code 1 -3. Prevent startup with invalid configuration - -This ensures secure and reliable operation. diff --git a/docs/ERROR_HANDLING_GUIDE.md b/docs/ERROR_HANDLING_GUIDE.md deleted file mode 100644 index 6cbf5013..00000000 --- a/docs/ERROR_HANDLING_GUIDE.md +++ /dev/null @@ -1,571 +0,0 @@ -# Centralized Error Handling Guide - -Comprehensive error handling system with consistent formatting, proper HTTP status codes, and security-focused responses. - -## 📋 Table of Contents - -- [Overview](#overview) -- [Quick Start](#quick-start) -- [Error Codes](#error-codes) -- [Exception Classes](#exception-classes) -- [Error Response Format](#error-response-format) -- [Usage Examples](#usage-examples) -- [Development vs Production](#development-vs-production) -- [Best Practices](#best-practices) - ---- - -## 🎯 Overview - -This error handling system provides: - -✅ **Consistent Error Responses** - Same format across entire API -✅ **Proper HTTP Status Codes** - 400, 401, 403, 404, 409, 500, etc. -✅ **Error Codes** - Programmatic handling for frontend -✅ **Field-Level Validation** - Detailed validation errors -✅ **Security** - Hide sensitive data in production -✅ **Correlation IDs** - Track requests across services -✅ **Comprehensive Logging** - Full context for debugging - ---- - -## 🚀 Quick Start - -### 1. Import Error Handling Module - -Add to your main application module: - -```typescript -// src/app.module.ts -import { Module } from '@nestjs/common'; -import { ErrorHandlingModule } from './common/errors'; - -@Module({ - imports: [ - ErrorHandlingModule, // Add this line - // ... other modules - ], -}) -export class AppModule {} -``` - -That's it! The global exception filter is now active. - -### 2. Use Custom Exceptions in Your Code - -```typescript -import { NotFoundException, ValidationException } from './common/errors'; - -@Controller('users') -class UsersController { - @Get(':id') - async getUser(@Param('id') id: string) { - const user = await this.usersService.findById(id); - - if (!user) { - throw new NotFoundException('User', id); - } - - return user; - } -} -``` - ---- - -## 🔖 Error Codes - -### Authentication Errors (401) - -| Code | Message | Description | -|------|---------|-------------| -| `AUTH_TOKEN_EXPIRED` | Token has expired | JWT token expired | -| `AUTH_INVALID_CREDENTIALS` | Invalid credentials | Wrong username/password | -| `AUTH_INVALID_TOKEN` | Invalid token | Malformed or invalid token | -| `AUTH_MISSING_TOKEN` | Authentication required | No token provided | -| `AUTH_SESSION_EXPIRED` | Session expired | User session expired | - -### Authorization Errors (403) - -| Code | Message | Description | -|------|---------|-------------| -| `INSUFFICIENT_PERMISSIONS` | Access denied | User lacks required permissions | -| `ACCESS_DENIED` | Access denied | General authorization failure | -| `ROLE_REQUIRED` | Role required | Specific role needed | - -### Validation Errors (400) - -| Code | Message | Description | -|------|---------|-------------| -| `VALIDATION_FAILED` | Validation failed | Request validation failed | -| `INVALID_REQUEST_BODY` | Invalid request body | Malformed JSON | -| `INVALID_QUERY_PARAMS` | Invalid parameters | Bad query parameters | -| `MISSING_REQUIRED_FIELD` | Required field missing | Missing mandatory field | - -### Not Found Errors (404) - -| Code | Message | Description | -|------|---------|-------------| -| `RESOURCE_NOT_FOUND` | Resource not found | Entity doesn't exist | -| `ENDPOINT_NOT_FOUND` | Endpoint not found | URL doesn't exist | - -### Conflict Errors (409) - -| Code | Message | Description | -|------|---------|-------------| -| `DUPLICATE_RESOURCE` | Duplicate resource | Resource already exists | -| `RESOURCE_CONFLICT` | Resource conflict | Conflicting operation | -| `UNIQUE_CONSTRAINT_VIOLATION` | Unique constraint violated | Duplicate unique field | - -### Rate Limiting (429) - -| Code | Message | Description | -|------|---------|-------------| -| `RATE_LIMIT_EXCEEDED` | Too many requests | Rate limit exceeded | - -### Database Errors (500/503) - -| Code | Message | Description | -|------|---------|-------------| -| `DATABASE_ERROR` | Database error | General database error | -| `DATABASE_CONNECTION_FAILED` | Connection failed | Can't connect to DB | -| `DATABASE_TIMEOUT` | Timeout | Database operation timed out | - -### Server Errors (500) - -| Code | Message | Description | -|------|---------|-------------| -| `INTERNAL_SERVER_ERROR` | Internal server error | Unexpected error | -| `SERVICE_UNAVAILABLE` | Service unavailable | Service temporarily down | - ---- - -## 📦 Exception Classes - -### Base Exception - -All custom exceptions extend `AppException`: - -```typescript -throw new AppException( - 'Error message', - ErrorCode.VALIDATION_FAILED, - HttpStatus.BAD_REQUEST, - fieldErrors, // optional - context, // optional -); -``` - -### Common Exceptions - -#### Authentication - -```typescript -throw new TokenExpiredException(); -throw new InvalidCredentialsException('Invalid email or password'); -throw new AuthenticationException('Authentication required'); -``` - -#### Authorization - -```typescript -throw new AuthorizationException('You do not have permission to access this resource'); -``` - -#### Validation - -```typescript -throw new ValidationException('Validation failed', [ - { field: 'email', message: 'Invalid email format' }, - { field: 'password', message: 'Password must be at least 8 characters' }, -]); -``` - -#### Not Found - -```typescript -throw new NotFoundException('User', userId); -// "User with ID 123 not found" -``` - -#### Conflict - -```typescript -throw new DuplicateResourceException('User', 'email'); -// "A User with this email already exists" -``` - -#### Rate Limiting - -```typescript -throw new RateLimitException('Too many requests from this IP'); -``` - -#### Database - -```typescript -throw new DatabaseException('Failed to save user', originalError); -throw new DatabaseConnectionException(originalError); -``` - ---- - -## 📝 Error Response Format - -### Standard Structure - -```json -{ - "statusCode": 400, - "errorCode": "VALIDATION_FAILED", - "message": "Validation failed", - "details": [ - { - "field": "email", - "message": "Invalid email format" - } - ], - "correlationId": "req_1234567890_abc", - "timestamp": "2026-03-27T10:30:00.000Z", - "path": "/api/v1/users" -} -``` - -### Development Mode (with stack trace) - -```json -{ - "statusCode": 500, - "errorCode": "INTERNAL_SERVER_ERROR", - "message": "Database connection failed", - "correlationId": "req_1234567890_abc", - "timestamp": "2026-03-27T10:30:00.000Z", - "path": "/api/v1/users", - "meta": { - "stack": "Error: Database connection failed\n at ...", - "originalError": "ECONNREFUSED" - } -} -``` - -### Production Mode (sanitized) - -```json -{ - "statusCode": 500, - "errorCode": "INTERNAL_SERVER_ERROR", - "message": "Internal server error", - "correlationId": "req_1234567890_abc", - "timestamp": "2026-03-27T10:30:00.000Z", - "path": "/api/v1/users" -} -``` - ---- - -## 💡 Usage Examples - -### Example 1: Controller with Error Handling - -```typescript -import { Controller, Get, Post, Body, Param } from '@nestjs/common'; -import { - NotFoundException, - DuplicateResourceException, - ValidationException -} from './common/errors'; - -@Controller('users') -export class UsersController { - - @Get(':id') - async getUser(@Param('id') id: string) { - const user = await this.usersService.findById(id); - - if (!user) { - throw new NotFoundException('User', id); - } - - return user; - } - - @Post() - async createUser(@Body() createUserDto: CreateUserDto) { - try { - // Check for duplicates - const existing = await this.usersService.findByEmail(createUserDto.email); - - if (existing) { - throw new DuplicateResourceException('User', 'email'); - } - - return await this.usersService.create(createUserDto); - } catch (error) { - // Re-throw our custom exceptions - // Global filter will handle formatting - throw error; - } - } -} -``` - -### Example 2: Service Layer Validation - -```typescript -import { Injectable } from '@nestjs/common'; -import { ValidationException, NotFoundException } from './common/errors'; - -@Injectable() -export class UsersService { - - async updateEmail(userId: string, newEmail: string) { - // Validate email format - if (!this.isValidEmail(newEmail)) { - throw new ValidationException('Invalid email format', [ - { field: 'email', message: 'Must be a valid email address' }, - ]); - } - - // Check if user exists - const user = await this.findById(userId); - if (!user) { - throw new NotFoundException('User', userId); - } - - // Check for duplicates - const existing = await this.findByEmail(newEmail); - if (existing && existing.id !== userId) { - throw new DuplicateResourceException('User', 'email'); - } - - return this.update(user.id, { email: newEmail }); - } - - private isValidEmail(email: string): boolean { - return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); - } -} -``` - -### Example 3: Using Error Formatter Service - -```typescript -import { Controller, Inject } from '@nestjs/common'; -import { ErrorFormatterService } from './common/errors'; - -@Controller('reports') -export class ReportsController { - constructor( - @Inject(ErrorFormatterService) - private errorFormatter: ErrorFormatterService, - ) {} - - @Get(':id') - async getReport(@Param('id') id: string) { - try { - const report = await this.reportsService.findById(id); - - if (!report) { - // Manually create error response if needed - return this.errorFormatter.createNotFoundError('Report', id); - } - - return report; - } catch (error) { - // Or just throw exception - filter handles it - throw error; - } - } -} -``` - ---- - -## 🔧 Development vs Production - -### Environment Configuration - -Set `NODE_ENV` appropriately: - -```bash -# .env.development -NODE_ENV=development - -# .env.production -NODE_ENV=production -``` - -### Differences - -| Feature | Development | Production | -|---------|-------------|------------| -| Stack Traces | ✅ Shown | ❌ Hidden | -| Original Error Messages | ✅ Shown | ❌ Sanitized | -| Sensitive Data | ⚠️ Partially shown | ❌ Redacted | -| Error Context | ✅ Included | ❌ Minimal | -| Logging Level | Debug/Warn | Error only | - -### Example: Same Error in Different Environments - -**Development:** -```json -{ - "statusCode": 500, - "errorCode": "DATABASE_ERROR", - "message": "Cannot read property 'id' of undefined", - "meta": { - "stack": "TypeError: Cannot read property 'id'...\n at UserService.findById...", - "context": { - "userId": "123", - "query": "SELECT * FROM users WHERE id = '123'" - } - } -} -``` - -**Production:** -```json -{ - "statusCode": 500, - "errorCode": "DATABASE_ERROR", - "message": "A database error occurred" -} -``` - ---- - -## 🎓 Best Practices - -### DO ✅ - -- **Use custom exceptions** for known error scenarios -- **Include correlation IDs** for tracking -- **Provide field-level details** for validation errors -- **Log full error context** for debugging -- **Sanitize errors** in production -- **Use appropriate HTTP status codes** -- **Document error codes** for frontend developers - -### DON'T ❌ - -- **Don't expose stack traces** in production -- **Don't leak database errors** to clients -- **Don't show internal paths** or file names -- **Don't reveal environment variables** -- **Don't use generic 500** for client errors -- **Don't swallow errors** silently -- **Don't log sensitive data** (passwords, tokens) - ---- - -## 📊 HTTP Status Code Mapping - -| Error Type | HTTP Code | When to Use | -|------------|-----------|-------------| -| Validation | 400 | Invalid input data | -| Authentication | 401 | Missing/invalid token | -| Authorization | 403 | Insufficient permissions | -| Not Found | 404 | Resource doesn't exist | -| Conflict | 409 | Duplicate resource | -| Rate Limit | 429 | Too many requests | -| Database | 500/503 | Database errors | -| Server | 500 | Unexpected errors | - ---- - -## 🔍 Correlation IDs - -Every error includes a correlation ID for request tracking: - -```json -{ - "correlationId": "req_1711540200000_abc123" -} -``` - -### How It Works - -1. Client sends request with `X-Correlation-ID` header (optional) -2. System generates ID if not provided -3. ID included in all logs and error responses -4. Use ID to trace request through services - -### Usage - -```bash -# Client includes correlation ID -curl -H "X-Correlation-ID: my-custom-id-123" \ - https://api.example.com/users -``` - ---- - -## 🛡️ Security Features - -### Automatic Protection - -- ✅ Stack traces hidden in production -- ✅ Sensitive fields redacted from logs -- ✅ Database errors sanitized -- ✅ Internal paths concealed -- ✅ Environment variables protected - -### What Gets Redacted - -Logs automatically redact: -- Passwords -- Tokens -- API keys -- Secrets -- Credit card numbers - ---- - -## 📈 Performance - -- **Overhead**: <0.5ms per request -- **Memory**: Minimal (~50KB) -- **No blocking**: All logging is async -- **Efficient**: Single global filter instance - ---- - -## 🧪 Testing - -```typescript -describe('Error Handling', () => { - it('should return 404 for non-existent user', async () => { - const response = await request(app.getHttpServer()) - .get('/users/999') - .expect(404); - - expect(response.body).toMatchObject({ - statusCode: 404, - errorCode: 'RESOURCE_NOT_FOUND', - message: expect.stringContaining('not found'), - }); - }); - - it('should include correlation ID in error response', async () => { - const response = await request(app.getHttpServer()) - .get('/users/invalid') - .expect(400); - - expect(response.body.correlationId).toBeDefined(); - }); -}); -``` - ---- - -## 📚 Related Documentation - -- [API Error Response Standards](./API_ERROR_STANDARDS.md) -- [Logging Configuration](./LOGGING_GUIDE.md) -- [Security Best Practices](./SECURITY_GUIDE.md) - ---- - -**Last Updated**: March 27, 2026 -**Version**: 1.0.0 -**Maintained by**: PropChain Backend Team diff --git a/docs/LOAD_TESTING.md b/docs/LOAD_TESTING.md deleted file mode 100644 index 4e404f5e..00000000 --- a/docs/LOAD_TESTING.md +++ /dev/null @@ -1,44 +0,0 @@ -# Load Testing Guide - -This repository now includes a dedicated load testing suite to satisfy #140. - -## Tools -- k6 (https://k6.io) - -## Location -- `loadtests/propchain-loadtest.js` - -## Running locally -1. Install dependencies: - ```bash - npm ci - npm install --save-dev k6 - ``` -2. Set env vars: - ```bash - export API_URL=http://localhost:3000 - export TEST_USER_EMAIL=loadtest@propchain.local - export TEST_USER_PASSWORD=Password123! - ``` -3. Start the backend in a separate terminal: - ```bash - npm run start - ``` -4. Run load test: - ```bash - npm run loadtest - ``` - -## CI integration -- Workflow: `.github/workflows/ci.yml` -- Job: `load-test` -- Command: `npm run loadtest:ci` -- Results are saved as artifact `k6-results` in JSON format. - -## Performance criteria -- http_req_failed: < 1% -- 95th percentile response time: < 600ms - -## To add scenarios -- Edit `loadtests/propchain-loadtest.js` with more groups/endpoints. -- Add custom thresholds for endpoint-level behavior. diff --git a/docs/MODULE_ORGANIZATION_GUIDE.md b/docs/MODULE_ORGANIZATION_GUIDE.md deleted file mode 100644 index c2908570..00000000 --- a/docs/MODULE_ORGANIZATION_GUIDE.md +++ /dev/null @@ -1,465 +0,0 @@ -# Module Organization Guide - -This guide outlines the standardized module organization patterns for the PropChain Backend project to ensure consistency, maintainability, and scalability across the codebase. - -## Table of Contents - -- [Standard Module Structure](#standard-module-structure) -- [Naming Conventions](#naming-conventions) -- [Import/Export Patterns](#importexport-patterns) -- [Dependency Injection Patterns](#dependency-injection-patterns) -- [Code Documentation Standards](#code-documentation-standards) -- [Testing Patterns](#testing-patterns) -- [Module Organization Service](#module-organization-service) - -## Standard Module Structure - -Every module should follow this standardized structure: - -``` -src/[module-name]/ -├── [module-name].module.ts # Module definition -├── [module-name].controller.ts # HTTP request handling -├── [module-name].service.ts # Business logic -├── [module-name].entity.ts # Database entity -├── [module-name].repository.ts # Data access layer (optional) -├── dto/ # Data Transfer Objects -│ ├── create-[module-name].dto.ts -│ ├── update-[module-name].dto.ts -│ └── [module-name].response.dto.ts -├── guards/ # Authentication/authorization guards -│ └── [module-name].guard.ts -├── interceptors/ # Request/response interceptors -│ └── [module-name].interceptor.ts -├── middleware/ # Express middleware -│ └── [module-name].middleware.ts -├── utils/ # Utility functions -│ └── [module-name].utils.ts -├── types/ # TypeScript types -│ └── [module-name].types.ts -├── constants/ # Module constants -│ └── [module-name].constants.ts -└── tests/ # Test files - ├── [module-name].service.spec.ts - ├── [module-name].controller.spec.ts - └── [module-name].e2e.spec.ts -``` - -### Required Files - -Every module must include: -- `[module-name].module.ts` - Module definition and dependencies -- `[module-name].service.ts` - Business logic implementation -- `[module-name].controller.ts` - HTTP request handling -- `dto/` directory with at least `create-[module-name].dto.ts` - -### Optional Files - -These files should be included when needed: -- `[module-name].entity.ts` - For database entities -- `[module-name].repository.ts` - Custom repository implementations -- `guards/` - For authentication/authorization logic -- `interceptors/` - For request/response transformation -- `middleware/` - For Express middleware -- `tests/` - For unit and integration tests - -## Naming Conventions - -### Files and Directories - -- **Files**: kebab-case (e.g., `user-service.ts`, `create-user.dto.ts`) -- **Directories**: kebab-case (e.g., `dto/`, `guards/`, `interceptors/`) -- **Modules**: PascalCase (e.g., `UserModule`, `PropertyModule`) -- **Classes**: PascalCase (e.g., `UserService`, `PropertyController`) -- **Methods**: camelCase (e.g., `createUser()`, `findById()`) -- **Properties**: camelCase (e.g., `userName`, `propertyId`) -- **Constants**: UPPER_SNAKE_CASE (e.g., `MAX_RETRY_ATTEMPTS`, `DEFAULT_TIMEOUT`) -- **Private Properties**: underscore prefix (e.g., `_logger`, `_cache`) - -### DTO Naming - -- **Create DTOs**: `Create[EntityName]Dto` (e.g., `CreateUserDto`) -- **Update DTOs**: `Update[EntityName]Dto` (e.g., `UpdateUserDto`) -- **Response DTOs**: `[EntityName]ResponseDto` (e.g., `UserResponseDto`) -- **Query DTOs**: `[EntityName]QueryDto` (e.g., `UserQueryDto`) - -### Test Naming - -- **Unit Tests**: `[entity].service.spec.ts`, `[entity].controller.spec.ts` -- **Integration Tests**: `[entity].integration.spec.ts` -- **E2E Tests**: `[entity].e2e.spec.ts` - -## Import/Export Patterns - -### Import Order - -Imports should be organized in this specific order: - -1. **External Libraries** (node_modules) - ```typescript - import { Injectable, Logger } from '@nestjs/common'; - import { ConfigService } from '@nestjs/config'; - import * as fs from 'fs'; - import * as path from 'path'; - ``` - -2. **NestJS Modules** - ```typescript - import { TypeOrmModule } from '@nestjs/typeorm'; - import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; - ``` - -3. **Internal Modules** (different directories) - ```typescript - import { UserService } from '../users/user.service'; - import { PropertyEntity } from '../properties/property.entity'; - ``` - -4. **Relative Imports** (same module) - ```typescript - import { CreateUserDto } from './dto/create-user.dto'; - import { UserEntity } from './user.entity'; - ``` - -5. **Type-Only Imports** - ```typescript - import type { Request } from 'express'; - import type { User } from '../users/user.types'; - ``` - -### Export Patterns - -Module should export: - -```typescript -// Service exports -export { UserService } from './user.service'; - -// Controller exports -export { UserController } from './user.controller'; - -// DTO exports -export { CreateUserDto, UpdateUserDto } from './dto'; -export type { UserResponseDto } from './dto/user.response.dto'; - -// Entity exports -export { UserEntity } from './user.entity'; -``` - -## Dependency Injection Patterns - -### Constructor Injection (Preferred) - -```typescript -constructor( - private readonly userService: UserService, - private readonly configService: ConfigService, - private readonly logger: Logger, -) {} -``` - -### Repository Injection - -```typescript -constructor( - @InjectRepository(User) - private readonly userRepository: Repository, -) {} -``` - -### Custom Token Injection - -```typescript -constructor( - @Inject(USER_SERVICE_TOKEN) - private readonly userService: UserService, -) {} -``` - -### Forward References (Circular Dependencies) - -```typescript -constructor( - @Inject(forwardRef(() => CircularService)) - private readonly circularService: CircularService, -) {} -``` - -## Code Documentation Standards - -### File Headers - -Every file should start with a comprehensive header: - -```typescript -/** - * User Service - * - * Handles business logic for user management operations including: - * - User creation and authentication - * - Profile management - * - Permission handling - * - * @class UserService - * @constructor - * @param {Repository} userRepository - Database repository - * @param {ConfigService} configService - Configuration service - * @param {Logger} logger - Logging service - * - * @author PropChain Team - * @since 2024-01-15 - */ -``` - -### Method Documentation - -```typescript -/** - * Create a new user with validation and security checks - * - * @param {CreateUserDto} createUserDto - User creation data - * @param {Request} req - HTTP request context - * @returns {Promise} Created user entity - * - * @throws {BadRequestException} When validation fails - * @throws {ConflictException} When user already exists - * - * @example - * ```typescript - * const user = await userService.createUser({ - * email: 'user@example.com', - * password: 'securePassword123' - * }, request); - * ``` - */ -async createUser(createUserDto: CreateUserDto, req: Request): Promise { - // Implementation -} -``` - -### Class Documentation - -```typescript -/** - * User Controller - * - * Handles HTTP requests for user management endpoints. - * Implements authentication, authorization, and validation. - * - * @class UserController - * @constructor - * @param {UserService} userService - Business logic service - * - * @route /api/users - * @version 1.0.0 - */ -@Controller('users') -@UseGuards(JwtAuthGuard) -export class UserController { - // Implementation -} -``` - -## Testing Patterns - -### Service Testing - -```typescript -describe('UserService', () => { - let service: UserService; - let repository: Repository; - - beforeEach(async () => { - const module = await Test.createTestingModule({ - providers: [ - UserService, - { - provide: getRepositoryToken(User), - useValue: { - create: jest.fn(), - save: jest.fn(), - find: jest.fn(), - findOne: jest.fn(), - update: jest.fn(), - delete: jest.fn(), - }, - }, - ], - }).compile(); - - service = module.get(UserService); - repository = module.get>(getRepositoryToken(User)); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); - - describe('createUser', () => { - it('should create a new user successfully', async () => { - // Test implementation - }); - - it('should throw error for duplicate email', async () => { - // Test implementation - }); - }); -}); -``` - -### Controller Testing - -```typescript -describe('UserController', () => { - let controller: UserController; - let service: UserService; - - beforeEach(async () => { - const module = await Test.createTestingModule({ - controllers: [UserController], - providers: [ - { - provide: UserService, - useValue: { - createUser: jest.fn(), - findAll: jest.fn(), - findOne: jest.fn(), - update: jest.fn(), - remove: jest.fn(), - }, - }, - ], - }).compile(); - - controller = module.get(UserController); - service = module.get(UserService); - }); - - it('should be defined', () => { - expect(controller).toBeDefined(); - }); -}); -``` - -## Module Organization Service - -The project includes a `ModuleOrganizationService` that provides utilities for: - -- **Analyzing existing module structure** -- **Generating standardized module files** -- **Validating compliance with standards** -- **Reorganizing existing modules** -- **Discovering all modules in the project** - -### Usage Examples - -```typescript -// Analyze a module -const analysis = moduleOrgService.analyzeModuleStructure('./src/users'); - -// Create a new module structure -moduleOrgService.createModuleStructure('notifications', './src/notifications'); - -// Generate module files -moduleOrgService.generateModuleFiles('notifications', './src/notifications'); - -// Validate all modules -const validation = moduleOrgService.validateAllModules('./src'); -``` - -## Best Practices - -### 1. Separation of Concerns - -- Keep controllers thin (only HTTP handling) -- Put business logic in services -- Use repositories for data access -- Separate validation in DTOs - -### 2. Dependency Management - -- Use constructor injection for required dependencies -- Use optional injection for non-critical dependencies -- Avoid circular dependencies with forward references - -### 3. Error Handling - -- Use NestJS built-in exceptions -- Create custom exceptions for domain-specific errors -- Implement proper error logging - -### 4. Performance - -- Use lazy loading for large modules -- Implement caching where appropriate -- Optimize database queries - -### 5. Security - -- Validate all input data -- Implement proper authentication/authorization -- Use environment variables for sensitive data - -## Migration Guide - -### For Existing Modules - -1. **Analyze current structure** - ```bash - npm run module:analyze --module=users - ``` - -2. **Generate recommendations** - ```bash - npm run module:recommend --module=users - ``` - -3. **Apply reorganization** - ```bash - npm run module:reorganize --module=users - ``` - -### For New Modules - -1. **Create module structure** - ```bash - npm run module:create --name=notifications - ``` - -2. **Generate files** - ```bash - npm run module:generate --name=notifications - ``` - -3. **Add to app module** - ```typescript - import { NotificationsModule } from './notifications/notifications.module'; - - @Module({ - imports: [NotificationsModule], - // ... - }) - export class AppModule {} - ``` - -## Tools and Utilities - -The project provides several CLI tools for module management: - -- `npm run module:analyze` - Analyze module structure -- `npm run module:create` - Create new module -- `npm run module:generate` - Generate module files -- `npm run module:validate` - Validate all modules -- `npm run module:reorganize` - Reorganize existing module - -## Conclusion - -Following these standardized patterns ensures: - -- **Consistency** across all modules -- **Maintainability** with clear structure -- **Scalability** for future growth -- **Developer productivity** with predictable patterns -- **Code quality** through enforced standards - -For questions or contributions to these patterns, please refer to the development team or create an issue in the project repository. diff --git a/docs/PERFORMANCE.md b/docs/PERFORMANCE.md deleted file mode 100644 index 8ea64d5d..00000000 --- a/docs/PERFORMANCE.md +++ /dev/null @@ -1,535 +0,0 @@ -# Middleware Stack Performance Analysis - -> Comprehensive performance benchmarking of middleware stack configurations in PropChain NestJS application. - -## Executive Summary - -This document provides detailed performance analysis of different middleware stack configurations used in the PropChain application. We measure the cumulative cost of stacking multiple middleware and identify performance bottlenecks. - -### Key Findings - -- **Minimal Stack** (Logger + Error Handler): Baseline performance with ~0.5ms average response time -- **Auth Stack** (JWT + Rate Limit + Logger): ~1.2ms overhead (~140% increase over baseline) -- **Full Stack** (All production middleware): ~3.5ms overhead (~600% increase over baseline) - -### Performance Ranking - -| Rank | Stack | Avg Response Time | RPS | Score | -|------|-------|------------------|-----|-------| -| 1 | Minimal Stack | ~0.5ms | ~2000 | 95.2 | -| 2 | Auth Stack | ~1.7ms | ~588 | 78.4 | -| 3 | Full Stack | ~4.0ms | ~250 | 52.1 | - -## Benchmark Methodology - -### Test Configuration - -- **Iterations**: 1000 requests per stack -- **Concurrency**: 10 concurrent requests -- **Warmup**: 100 iterations to stabilize performance -- **Environment**: Production-like test environment - -### Environment Specifications - -``` -Node.js: v18.x or later -Platform: Linux/Windows/macOS -CPU: Multi-core (8+ cores recommended) -Memory: 16GB+ RAM -NestJS: ^10.3.0 -``` - -### Metrics Collected - -- **Response Time**: Min, Max, Average, Median, P95, P99 -- **Throughput**: Requests per second (RPS) -- **Error Rate**: Percentage of failed requests -- **Resource Usage**: Memory and CPU utilization - -## Stack Configurations - -### 1. Minimal Stack - -**Purpose**: Bare minimum production configuration - -**Components**: -- `LoggingMiddleware` - Request correlation and structured logging -- `AllExceptionsFilter` - Global error handling and logging - -**Use Case**: Internal services, low-risk endpoints, development environments - -**Performance Profile**: -- Average Response Time: ~0.5ms -- P95 Latency: ~0.8ms -- P99 Latency: ~1.2ms -- Throughput: ~2000 RPS -- Memory Overhead: Minimal (<1MB) - -```typescript -// benchmarks/chains/stacks/minimal.stack.ts -@Module({ - imports: [ConfigModule], - providers: [LoggerService], -}) -export class MinimalStackModule implements INestModule { - configure(consumer: MiddlewareConsumer): void { - consumer.apply(LoggingMiddleware).forRoutes({ - path: '*', - method: RequestMethod.ALL, - }); - } -} -``` - -### 2. Auth Stack - -**Purpose**: Authentication-focused endpoints requiring security - -**Components**: -- `LoggingMiddleware` - Request correlation -- `AdvancedRateLimitGuard` - Tiered rate limiting -- `JwtAuthGuard` - JWT token validation and session management -- `AllExceptionsFilter` - Error handling - -**Use Case**: User-facing APIs, authenticated endpoints, sensitive operations - -**Performance Profile**: -- Average Response Time: ~1.7ms -- P95 Latency: ~2.5ms -- P99 Latency: ~3.8ms -- Throughput: ~588 RPS -- Memory Overhead: Moderate (~5MB) - -**Overhead Breakdown**: -- JWT Validation: ~0.8ms (47%) -- Rate Limiting: ~0.3ms (18%) -- Logging: ~0.1ms (6%) -- Base Overhead: ~0.5ms (29%) - -```typescript -// benchmarks/chains/stacks/auth.stack.ts -@Module({ - imports: [ConfigModule], - providers: [LoggerService], -}) -export class AuthStackModule implements INestModule { - configure(consumer: MiddlewareConsumer): void { - consumer.apply(LoggingMiddleware).forRoutes({ - path: '*', - method: RequestMethod.ALL, - }); - // Rate limiting and JWT guards applied at route level - } -} -``` - -### 3. Full Stack - -**Purpose**: Complete production security and performance stack - -**Components**: -- `LoggingMiddleware` - Request correlation -- `SecurityMiddleware` - IP blocking, DDoS protection -- `AdvancedRateLimitGuard` - Advanced rate limiting -- `HeaderValidationMiddleware` - Header security checks -- `ApiVersionMiddleware` - API versioning -- `CompressionMiddleware` - Response compression -- `Helmet` - Security headers -- `AllExceptionsFilter` - Error handling - -**Use Case**: Public APIs, high-security endpoints, production deployments - -**Performance Profile**: -- Average Response Time: ~4.0ms -- P95 Latency: ~6.2ms -- P99 Latency: ~9.5ms -- Throughput: ~250 RPS -- Memory Overhead: Significant (~15MB) - -**Overhead Breakdown**: -- Security Checks (IP/DDoS): ~1.2ms (30%) -- Compression: ~0.8ms (20%) -- Rate Limiting: ~0.5ms (12.5%) -- Header Validation: ~0.4ms (10%) -- API Versioning: ~0.2ms (5%) -- JWT Validation: ~0.8ms (20%) -- Logging: ~0.1ms (2.5%) - -```typescript -// benchmarks/chains/stacks/full.stack.ts -@Module({ - imports: [ConfigModule], - providers: [LoggerService], -}) -export class FullStackModule implements INestModule { - configure(consumer: MiddlewareConsumer): void { - consumer.apply(LoggingMiddleware).forRoutes({ - path: '*', - method: RequestMethod.ALL, - }); - // Additional middleware applied in production - } -} -``` - -## Baseline Comparison - -All stacks compared against bare Express server (no middleware): - -| Stack | Absolute Overhead | Relative Overhead | Significantly Slower | -|-------|------------------|-------------------|---------------------| -| Minimal Stack | +0.3ms | +150% | No | -| Auth Stack | +1.5ms | +400% | Yes | -| Full Stack | +3.8ms | +950% | Yes | - -## Component Overhead Analysis - -### Individual Component Costs - -| Component | Avg Overhead (ms) | % of Total | Bottleneck | -|-----------|------------------|------------|------------| -| SecurityMiddleware (DDoS/IP) | 1.2 | 30% | ⚠️ Yes | -| CompressionMiddleware | 0.8 | 20% | ⚠️ Yes | -| JwtAuthGuard | 0.8 | 20% | ⚠️ Yes | -| AdvancedRateLimitGuard | 0.5 | 12.5% | ✅ No | -| HeaderValidationMiddleware | 0.4 | 10% | ✅ No | -| ApiVersionMiddleware | 0.2 | 5% | ✅ No | -| LoggingMiddleware | 0.1 | 2.5% | ✅ No | - -### Disproportionate Overhead Analysis - -The **Full Stack** shows **non-linear scaling** - the total overhead (4.0ms) is greater than the sum of individual components (~3.5ms). This indicates: - -1. **Shared State Contention**: Multiple middleware accessing Redis/cache simultaneously -2. **Blocking Calls**: Synchronous operations in security checks -3. **Memory Pressure**: Cumulative memory usage affecting GC frequency - -## Memory Profiling And Leak Detection - -Middleware latency is only half the story for long-running services. To catch silent retention issues, the repository now includes an in-process memory profiling harness under `benchmarks/memory/`. - -### Profiling Workflow - -1. Run a scenario with heap snapshots before and after a 10k request stress pass. -2. Compare `before.heapsnapshot` and `after.heapsnapshot` in Chrome DevTools. -3. Review `summary.json` for heap and RSS deltas after forced GC. -4. Investigate retained objects that remain reachable after the post-run GC. - -### Commands - -```bash -npm run bench:memory -npm run bench:memory -- --scenario=header-validation -npm run bench:memory -- --scenario=circuit-breaker --requests=10000 --concurrency=50 -``` - -### Output Artifacts - -Each run writes to `benchmarks/memory/output/-/`: - -- `before.heapsnapshot` -- `after.heapsnapshot` -- `summary.json` - -### Current Leak-Risk Findings - -These findings are the current cleanup priorities identified from middleware structure review and should be validated with the new heap snapshots: - -| Middleware | Risk | Why It Needs Cleanup Attention | -|------------|------|--------------------------------| -| `StaticCacheMiddleware` | High | Wraps response methods and stores cache metadata that can retain large payload references if cleanup paths are missed | -| `CircuitBreakerMiddleware` | Medium | Replaces `response.end` and keeps long-lived breaker state in memory | -| `TimeoutMiddleware` | Medium | Allocates per-request timers and uses timeout/rejection coordination that must release closures promptly | -| `HeaderValidationMiddleware` | Low | Attaches sanitized header objects to every request and should be checked for accidental retention under load | - -### Recommended Review Sequence - -1. Profile `baseline` to establish the control snapshot. -2. Profile `combined` to detect cumulative middleware retention. -3. Isolate the highest delta scenario with `header-validation` or `circuit-breaker`. -4. Extend `benchmarks/memory/scenarios.ts` with additional middleware targets such as `StaticCacheMiddleware` as dependencies are mocked or adapted. - -## Recommendations - -### High Priority (Immediate Action) - -#### 1. Optimize Security Middleware -- **Priority**: 1/5 -- **Category**: Performance -- **Complexity**: Medium -- **Expected Improvement**: 30-40% reduction in Full Stack overhead - -**Actions**: -- Cache IP reputation checks (TTL: 5 minutes) -- Async DDoS detection with background processing -- Implement circuit breaker for external security services - -```typescript -// Example: Cached IP checking -private readonly ipCache = new NodeCache({ stdTTL: 300 }); - -async shouldBlockRequest(ip: string): Promise { - const cached = this.ipCache.get(ip); - if (cached !== undefined) return cached as boolean; - - const result = await this.checkIpReputation(ip); - this.ipCache.set(ip, result.shouldBlock); - return result.shouldBlock; -} -``` - -#### 2. Lazy-Load Heavy Middleware -- **Priority**: 2/5 -- **Category**: Scalability -- **Complexity**: High -- **Expected Improvement**: 50% reduction for non-sensitive endpoints - -**Actions**: -- Apply compression only to large responses (>1KB) -- Skip DDoS checks for authenticated users with valid sessions -- Conditionally apply header validation based on endpoint sensitivity - -```typescript -// Example: Conditional compression -@Injectable() -export class SmartCompressionMiddleware implements NestMiddleware { - use(req: Request, res: Response, next: NextFunction) { - // Only compress for large responses - const originalSend = res.send.bind(res); - res.send = (data: any) => { - const size = Buffer.byteLength(JSON.stringify(data)); - if (size > 1024) { - // Apply compression - } - return originalSend(data); - }; - next(); - } -} -``` - -#### 3. Implement Async Rate Limiting -- **Priority**: 2/5 -- **Category**: Performance -- **Complexity**: Medium -- **Expected Improvement**: 20-30% reduction in Auth Stack overhead - -**Actions**: -- Use Redis pipelining for rate limit checks -- Implement sliding window algorithm for better accuracy -- Consider local caching with eventual consistency - -### Medium Priority (Short-term Improvements) - -#### 4. Optimize JWT Validation -- **Priority**: 3/5 -- **Category**: Performance -- **Complexity**: Low -- **Expected Improvement**: 15-20% reduction in Auth Stack overhead - -**Actions**: -- Cache decoded tokens (short TTL: 1-2 minutes) -- Use HS256 instead of RS256 for internal services -- Implement token introspection caching - -#### 5. Reduce Logging Overhead -- **Priority**: 4/5 -- **Category**: Performance -- **Complexity**: Low -- **Expected Improvement**: 5-10% overall improvement - -**Actions**: -- Async logging with buffered writes -- Sample high-volume endpoints (log 1 in 100 requests) -- Use log levels strategically (DEBUG vs INFO) - -### Low Priority (Long-term Optimizations) - -#### 6. Implement Middleware Pipeline Optimization -- **Priority**: 5/5 -- **Category**: Architecture -- **Complexity**: High -- **Expected Improvement**: 20-25% across all stacks - -**Actions**: -- Parallel execution of independent middleware -- Early exit optimization for failed checks -- Request batching for bulk operations - -## Running Benchmarks - -### Prerequisites - -```bash -npm install --save-dev ts-node @types/node -``` - -### Execute Benchmarks - -```bash -# Run with default settings (1000 iterations, 10 concurrency) -npx ts-node benchmarks/chains/run-benchmarks.ts - -# Custom configuration -npx ts-node benchmarks/chains/run-benchmarks.ts --iterations=5000 --concurrency=20 --output=custom-report.md -``` - -### Output - -The benchmark runner generates: -- Console output with real-time progress -- Markdown report with detailed analysis -- JSON data for further analysis (optional) - -## Monitoring in Production - -### Key Metrics to Track - -1. **Per-Middleware Latency** - ```typescript - // Example: Measure middleware execution time - @Injectable() - export class MetricsMiddleware implements NestMiddleware { - use(req: Request, res: Response, next: NextFunction) { - const start = Date.now(); - res.on('finish', () => { - const duration = Date.now() - start; - metrics.histogram('middleware.duration_ms', duration); - }); - next(); - } - } - ``` - -2. **Stack-Wide Performance** - - Track P95/P99 latency per endpoint - - Monitor RPS trends over time - - Alert on degradation >20% from baseline - -3. **Resource Utilization** - - Memory per request - - CPU time per middleware - - External service call latency (Redis, etc.) - -### Alerting Thresholds - -| Metric | Warning | Critical | -|--------|---------|----------| -| Avg Response Time | >2ms (Minimal), >5ms (Auth), >10ms (Full) | 2x baseline | -| P99 Latency | >10ms | >50ms | -| Error Rate | >1% | >5% | -| RPS Drop | >20% from baseline | >50% from baseline | - -## Continuous Benchmarking - -### CI/CD Integration - -Add benchmark checks to CI pipeline to prevent performance regressions: - -```yaml -# .github/workflows/benchmarks.yml -jobs: - benchmarks: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Run Middleware Benchmarks - run: npx ts-node benchmarks/chains/run-benchmarks.ts --iterations=1000 - - name: Upload Results - uses: actions/upload-artifact@v3 - with: - name: benchmark-results - path: docs/PERFORMANCE.md -``` - -### Performance Budget - -Set acceptable performance thresholds: - -```json -{ - "performanceBudget": { - "minimalStack": { - "avgMs": 1.0, - "p95Ms": 2.0, - "rps": 1000 - }, - "authStack": { - "avgMs": 3.0, - "p95Ms": 5.0, - "rps": 500 - }, - "fullStack": { - "avgMs": 8.0, - "p95Ms": 15.0, - "rps": 200 - } - } -} -``` - -## Conclusion - -### Key Takeaways - -1. **Middleware stacking has non-linear costs** - Each additional middleware adds more than its individual overhead due to shared state contention and blocking calls. - -2. **Security comes at a price** - The Full Stack provides comprehensive protection but costs 8x more than the Minimal Stack. - -3. **Optimization opportunities exist** - Caching, async operations, and lazy-loading can reduce Full Stack overhead by 40-50%. - -4. **Context matters** - Not all endpoints need the Full Stack. Use Minimal Stack for low-risk endpoints and Auth Stack for standard authenticated requests. - -### Best Practices - -✅ **DO**: -- Profile before optimizing - measure actual impact -- Use appropriate stack for each endpoint's risk level -- Implement caching for expensive operations -- Monitor performance in production continuously - -❌ **DON'T**: -- Apply Full Stack to every endpoint blindly -- Optimize without measuring first -- Ignore non-linear scaling effects -- Forget to re-benchmark after changes - -### Future Work - -- [ ] Implement parallel middleware execution -- [ ] Add adaptive middleware based on request context -- [ ] Create automated performance regression detection -- [ ] Build middleware performance dashboard -- [ ] Explore WebAssembly for CPU-intensive middleware - -## Appendix - -### A. Benchmark Source Code - -All benchmark code is located in `benchmarks/chains/`: -- `run-benchmarks.ts` - Main runner script -- `benchmark-runner.ts` - Benchmark execution logic -- `benchmark-reporter.ts` - Report generation -- `stacks/*.ts` - Stack configurations -- `types/*.ts` - Type definitions -- `utils/*.ts` - Utility functions - -### B. Statistical Methods - -- **Percentiles**: P95 (95th percentile), P99 (99th percentile) -- **Standard Deviation**: Measures variability in response times -- **Confidence Intervals**: 95% confidence for all measurements -- **Outlier Removal**: Requests >3σ from mean excluded - -### C. Related Documentation - -- [API Security Guide](./API_SECURITY_GUIDE.md) -- [Rate Limiting Implementation](./RATE_LIMITING_IMPLEMENTATION.md) -- [Database Optimization Guide](./DATABASE_OPTIMIZATION_GUIDE.md) -- [Load Testing](./LOAD_TESTING.md) - ---- - -**Last Updated**: March 27, 2026 -**Author**: PropChain Performance Team -**Review Cycle**: Quarterly diff --git a/docs/RATE_LIMITING_IMPLEMENTATION.md b/docs/RATE_LIMITING_IMPLEMENTATION.md deleted file mode 100644 index 796bb09b..00000000 --- a/docs/RATE_LIMITING_IMPLEMENTATION.md +++ /dev/null @@ -1,283 +0,0 @@ -# Rate Limiting Implementation for Sensitive Endpoints - -## Overview - -This document describes the implementation of enhanced rate limiting for sensitive authentication endpoints in the PropChain backend. The implementation addresses security issue #92 by adding stricter rate limits, IP-based blocking, and progressive delay mechanisms to prevent brute-force attacks and abuse. - -## Features Implemented - -### 1. Sensitive Endpoint Rate Limit Guard - -A new guard (`SensitiveEndpointRateLimitGuard`) has been created specifically for protecting sensitive endpoints with enhanced security features: - -- **Stricter rate limits** compared to standard API endpoints -- **Progressive delay mechanism** that increases delay time with repeated violations -- **IP-based blocking** after exceeding rate limits -- **Automatic IP blocking** with configurable duration -- **Whitelist support** to bypass rate limiting for trusted IPs -- **Comprehensive rate limit headers** in responses - -**Location:** `src/security/guards/sensitive-endpoint-rate-limit.guard.ts` - -### 2. Enhanced Rate Limiting on Authentication Endpoints - -#### Password Reset Endpoints - -**POST /auth/forgot-password** -- Rate limit: 3 requests per 15 minutes -- Progressive delay enabled -- IP blocking after exceeding limit (30 minutes block) -- Key prefix: `password_reset` - -**PUT /auth/reset-password** -- Rate limit: 5 requests per 15 minutes -- Progressive delay enabled -- IP blocking after exceeding limit (1 hour block) -- Key prefix: `password_reset_confirm` - -#### Token Refresh Endpoint - -**POST /auth/refresh-token** -- Rate limit: 10 requests per minute -- No progressive delay (to avoid impacting legitimate use) -- No automatic IP blocking -- Key prefix: `token_refresh` - -### 3. Enhanced Rate Limiting on MFA Endpoints - -**POST /mfa/verify** -- Rate limit: 5 attempts per 5 minutes -- Progressive delay enabled -- IP blocking after exceeding limit (30 minutes block) -- Key prefix: `mfa_verify` - -**POST /mfa/verify-backup** -- Rate limit: 10 attempts per 5 minutes -- Progressive delay enabled -- IP blocking after exceeding limit (1 hour block) -- Key prefix: `mfa_backup_verify` - -**POST /mfa/backup-codes** -- Rate limit: 3 requests per hour -- No progressive delay -- No automatic IP blocking -- Key prefix: `mfa_backup_gen` - -**DELETE /mfa/disable** -- Rate limit: 3 requests per hour -- No progressive delay -- No automatic IP blocking -- Key prefix: `mfa_disable` - -## Technical Implementation - -### Rate Limiting Strategy - -The implementation uses a **sliding window algorithm** with Redis for distributed rate limiting: - -1. Each request is tracked with a timestamp in a Redis sorted set -2. Expired entries are automatically removed before checking limits -3. Current count is compared against the configured maximum -4. Rate limit information is returned in response headers - -### Progressive Delay Mechanism - -When enabled, the progressive delay mechanism: - -1. Calculates excess attempts beyond the rate limit -2. Applies a delay of `attempts * 1000ms` (capped at 10 seconds) -3. Forces attackers to slow down their attempts -4. Does not impact legitimate users within limits - -### IP Blocking Integration - -The guard integrates with the existing `IpBlockingService`: - -1. Checks if IP is blocked before processing request -2. Checks if IP is whitelisted (bypasses all rate limiting) -3. Records failed attempts for tracking -4. Automatically blocks IPs when `blockOnExceed` is enabled -5. Configurable block duration per endpoint - -### Rate Limit Headers - -All rate-limited responses include the following headers: - -- `X-RateLimit-Limit`: Maximum requests allowed in the window -- `X-RateLimit-Remaining`: Remaining requests in current window -- `X-RateLimit-Reset`: Unix timestamp when the limit resets -- `Retry-After`: Seconds to wait before retrying (when blocked) - -## Configuration - -### Decorator Usage - -Apply rate limiting to any endpoint using the `@SensitiveRateLimit` decorator: - -```typescript -@Post('sensitive-operation') -@UseGuards(SensitiveEndpointRateLimitGuard) -@SensitiveRateLimit({ - windowMs: 300000, // 5 minutes - maxRequests: 5, // 5 requests max - keyPrefix: 'custom_prefix', // Redis key prefix - enableProgressiveDelay: true, - blockOnExceed: true, - blockDurationMs: 1800000, // 30 minutes block -}) -async sensitiveOperation() { - // Your implementation -} -``` - -### Configuration Options - -| Option | Type | Description | Default | -|--------|------|-------------|---------| -| `windowMs` | number | Time window in milliseconds | 60000 (1 min) | -| `maxRequests` | number | Maximum requests in window | 5 | -| `keyPrefix` | string | Redis key prefix | 'sensitive' | -| `enableProgressiveDelay` | boolean | Enable progressive delays | true | -| `blockOnExceed` | boolean | Block IP after exceeding | false | -| `blockDurationMs` | number | Block duration in ms | 3600000 (1 hour) | - -## Rate Limit Key Generation - -The guard generates rate limit keys in the following priority order: - -1. **User ID** (if authenticated): `user:{userId}` -2. **Email** (from request body): `email:{email}` -3. **IP Address** (fallback): `ip:{ipAddress}` - -This ensures: -- Authenticated users are tracked by user ID -- Password reset/registration tracked by email -- Anonymous requests tracked by IP - -## IP Address Extraction - -The guard extracts client IP addresses from: - -1. `x-forwarded-for` header (first IP in chain) -2. `x-real-ip` header -3. `connection.remoteAddress` -4. `socket.remoteAddress` - -This ensures correct IP detection behind proxies and load balancers. - -## Security Considerations - -### Fail-Open Design - -The guard is designed to fail open (allow requests) when: -- Redis connection fails -- Rate limiting service throws an error -- IP blocking service is unavailable - -This prevents security features from causing service outages while logging errors for investigation. - -### Protection Against Enumeration - -Password reset endpoints return generic messages regardless of whether the email exists, preventing user enumeration attacks. - -### Distributed Rate Limiting - -Using Redis ensures rate limits work correctly across multiple application instances in a distributed deployment. - -## Testing - -### Unit Tests - -Comprehensive unit tests cover: -- Rate limit enforcement -- IP blocking integration -- Whitelist functionality -- Progressive delay mechanism -- Header generation -- Key generation strategies -- Fail-open behavior - -**Location:** `test/security/guards/sensitive-endpoint-rate-limit.guard.spec.ts` - -### Integration Tests - -End-to-end tests verify: -- Password reset rate limiting -- MFA endpoint rate limiting -- Token refresh rate limiting -- Rate limit header accuracy -- IP-based tracking -- Rate limit reset behavior - -**Location:** `test/auth/sensitive-endpoints-rate-limit.e2e-spec.ts` - -## Monitoring and Logging - -All rate limit violations are logged with: -- Severity: WARN -- IP address -- Rate limit key -- Endpoint path -- Timestamp - -IP blocking events are logged with: -- Severity: WARN -- IP address -- Reason for blocking -- Block duration -- Timestamp - -## Migration Notes - -### Backward Compatibility - -The implementation is fully backward compatible: -- Existing endpoints continue to work -- No database migrations required -- No breaking API changes -- Existing rate limiting infrastructure is reused - -### Deployment Considerations - -1. Ensure Redis is available and configured -2. Review and adjust rate limit thresholds for your use case -3. Configure IP whitelisting for trusted sources -4. Monitor rate limit logs after deployment -5. Adjust block durations based on attack patterns - -## Performance Impact - -- **Minimal overhead**: Single Redis query per request -- **Efficient storage**: Automatic cleanup of expired entries -- **Scalable**: Distributed across Redis cluster -- **Non-blocking**: Async operations throughout - -## Future Enhancements - -Potential improvements for future iterations: - -1. **Adaptive rate limiting** based on user reputation -2. **Geographic IP blocking** for high-risk regions -3. **CAPTCHA integration** after multiple violations -4. **Machine learning** for anomaly detection -5. **Rate limit analytics dashboard** -6. **Customizable response messages** per endpoint -7. **Account-level rate limit overrides** for premium users - -## Related Files - -- Guard: `src/security/guards/sensitive-endpoint-rate-limit.guard.ts` -- Decorator: `src/security/decorators/sensitive-rate-limit.decorator.ts` -- Auth Controller: `src/auth/auth.controller.ts` -- MFA Controller: `src/auth/mfa/mfa.controller.ts` -- Security Module: `src/security/security.module.ts` -- Unit Tests: `test/security/guards/sensitive-endpoint-rate-limit.guard.spec.ts` -- E2E Tests: `test/auth/sensitive-endpoints-rate-limit.e2e-spec.ts` - -## Support - -For issues or questions regarding rate limiting: -1. Check logs for rate limit violations -2. Review Redis connection status -3. Verify IP whitelist configuration -4. Consult security team for threshold adjustments diff --git a/docs/SERVICE_LAYER_ARCHITECTURE.md b/docs/SERVICE_LAYER_ARCHITECTURE.md deleted file mode 100644 index 618fa719..00000000 --- a/docs/SERVICE_LAYER_ARCHITECTURE.md +++ /dev/null @@ -1,28 +0,0 @@ -# Service Layer Architecture - -Service classes should now follow a single pattern. - -## Base Pattern - -- Extend `BaseService` from `src/common/services/base.service.ts`. -- Validate inbound payloads with `BoundaryValidationService`. -- Transform outbound objects into DTOs at the service boundary when the response shape is public. -- Keep controllers thin and move normalization into the service layer. - -## Dependency Injection Rules - -- Import provider modules such as `PrismaModule`, `CacheModule`, and `BoundaryValidationModule` instead of manually re-providing shared services. -- Prefer constructor order: persistence, domain collaborators, config, validation. -- Use `private readonly` injections consistently. - -## Validation Rules - -- Treat controller validation as a first pass only. -- Re-validate data at service entry points when the method can be called internally or across modules. -- Use DTO transformation to normalize query strings, numeric inputs, and optional payloads before business logic runs. - -## Error Handling - -- Throw typed exceptions with structured `details`. -- Let the global exception filter preserve explicit `errorCode` values. -- Log failures once at the service boundary or exception filter, not in every nested helper. diff --git a/docs/ZERO_DOWNTIME_MIGRATIONS.md b/docs/ZERO_DOWNTIME_MIGRATIONS.md deleted file mode 100644 index 5bc093ec..00000000 --- a/docs/ZERO_DOWNTIME_MIGRATIONS.md +++ /dev/null @@ -1,59 +0,0 @@ -# Zero-Downtime Migrations - -This project now treats database migrations as an expand/contract workflow instead of a single-step schema rewrite. - -## Rules - -1. Additive changes first. -2. Keep old reads and writes working during rolling deploys. -3. Add a `rollback.sql` file to every migration directory. -4. Validate migrations before merge with `npm run migrate:validate`. -5. Test migrations against an empty database with `npm run migrate:test`. - -## Expand / Contract Pattern - -### Expand - -- Add nullable columns, new tables, or additive indexes. -- Backfill data in a separate step. -- Ship application code that can read both old and new shapes. - -### Contract - -- Remove old columns or constraints only after all running versions no longer depend on them. -- Treat destructive cleanup as a later migration, not part of the initial rollout. - -## Rollback Strategy - -Every migration directory must contain: - -- `migration.sql` -- `rollback.sql` - -`rollback.sql` is intended for operational rollback of the database change itself. Prisma migration history is still append-only, so preferred production recovery remains forward-fix plus restore-from-backup when needed. - -Dry-run the latest rollback plan with: - -```bash -npm run migrate:rollback:dry-run -``` - -Execute a rollback against the configured database with: - -```bash -node scripts/rollback-migration.js --name= -``` - -## Validation - -`npm run migrate:validate` checks for: - -- Missing `rollback.sql` -- Destructive SQL patterns that are not backward-compatible -- Non-concurrent index creation as a zero-downtime warning - -Use the explicit marker `-- @allow-breaking-change` only when a destructive migration has been reviewed and coordinated with a maintenance plan. - -## Testing - -`npm run migrate:test` runs the migration validator and a database integration test that applies Prisma migrations to a clean PostgreSQL test container. diff --git a/docs/enhanced-rate-limiting.md b/docs/enhanced-rate-limiting.md deleted file mode 100644 index 6aaf8adc..00000000 --- a/docs/enhanced-rate-limiting.md +++ /dev/null @@ -1,260 +0,0 @@ -# Enhanced Rate Limiting Implementation - -This document describes the enhanced rate limiting features implemented in the PropChain-BackEnd project. - -## Overview - -The enhanced rate limiting system provides: -- **Tiered Rate Limiting**: Different rate limits based on user subscription tiers -- **User-Based Rate Limits**: Personalized rate limiting per user -- **Rate Limit Analytics**: Comprehensive monitoring and analytics -- **Dynamic Tier Management**: Runtime tier assignment and management - -## Features - -### 1. Tiered Rate Limiting - -Four user tiers with different rate limits: - -| Tier | Requests/Minute | Use Case | -|------|-----------------|----------| -| FREE | 10 | Basic users, trial accounts | -| BASIC | 50 | Standard users | -| PREMIUM | 200 | Paid subscribers | -| ENTERPRISE | 1000 | Enterprise clients | - -### 2. User-Based Rate Limiting - -- Rate limits are applied per user ID, API key, or IP address -- User tiers are stored in Redis for fast lookup -- Automatic tier-based limit adjustment - -### 3. Rate Limit Analytics - -- Total request monitoring -- Blocked request tracking -- Top user identification -- Tier distribution analytics -- Time-windowed analytics - -### 4. Dynamic Tier Management - -- Runtime tier assignment -- Tier upgrade/downgrade capabilities -- Expiration-based tier reset -- Metadata tracking for audit - -## Implementation - -### Core Services - -#### RateLimitingService -- Handles rate limit checking and enforcement -- Supports tiered rate limiting -- Provides analytics tracking -- Manages Redis-based rate limit storage - -#### UserTierManagementService -- Manages user tier assignments -- Handles tier upgrades/downgrades -- Provides tier distribution statistics -- Manages tier expiration - -### Guards and Decorators - -#### AdvancedRateLimitGuard -- Enhanced guard supporting tiered rate limiting -- Automatic user tier detection -- Configurable rate limit options -- Comprehensive rate limit headers - -#### TieredRateLimit Decorator -- Easy-to-use decorator for endpoint protection -- Predefined decorators for common use cases -- Customizable rate limit options - -### Controllers - -#### RateLimitAnalyticsController -- `/admin/rate-limiting/analytics` - Get rate limiting analytics -- `/admin/rate-limiting/tiered-limits` - Get tiered limit configuration -- `/admin/rate-limiting/configurations` - Get default configurations - -#### UserTierManagementController -- `/admin/user-tiers/{userId}/tier` - Set user tier -- `/admin/user-tiers/{userId}/upgrade` - Upgrade user tier -- `/admin/user-tiers/{userId}/downgrade` - Downgrade user tier -- `/admin/user-tiers/distribution` - Get tier distribution - -## Usage Examples - -### Basic Tiered Rate Limiting - -```typescript -import { TieredRateLimit } from '../security/decorators/tiered-rate-limit.decorator'; - -@Get('api/data') -@TieredRateLimit({ - windowMs: 60000, // 1 minute - maxRequests: 100, // Base limit - useUserTier: true, // Enable tiered limits -}) -async getData() { - return { message: 'Data with tiered rate limiting' }; -} -``` - -### Predefined Decorators - -```typescript -import { - AuthRateLimit, - ExpensiveOperationRateLimit, - FreeTierRateLimit, - PremiumTierRateLimit -} from '../security/decorators/tiered-rate-limit.decorator'; - -@Post('auth/login') -@AuthRateLimit() // Strict limits for auth -async login() { } - -@Get('expensive') -@ExpensiveOperationRateLimit() // Tiered limits for expensive ops -async expensiveOperation() { } - -@Get('free-content') -@FreeTierRateLimit() // Fixed limits for free tier -async freeContent() { } -``` - -### Manual Tier Management - -```typescript -// Set user tier -await this.userTierManagementService.setUserTier('user123', UserTier.PREMIUM, 'Payment upgrade'); - -// Upgrade user tier -await this.userTierManagementService.upgradeUserTier('user123', UserTier.ENTERPRISE, 'Enterprise subscription'); - -// Get user tier with metadata -const { tier, metadata } = await this.userTierManagementService.getUserTierWithMetadata('user123'); -``` - -### Analytics - -```typescript -// Get rate limiting analytics -const analytics = await this.rateLimitingService.getRateLimitAnalytics(3600000); // 1 hour window - -console.log(`Total requests: ${analytics.totalRequests}`); -console.log(`Blocked requests: ${analytics.blockedRequests}`); -console.log(`Top users:`, analytics.topUsers); -console.log(`Tier distribution:`, analytics.tierDistribution); -``` - -## Configuration - -Environment variables for rate limiting: - -```bash -# Tier-specific rate limits (requests per minute) -RATE_LIMIT_FREE_PER_MINUTE=10 -RATE_LIMIT_BASIC_PER_MINUTE=50 -RATE_LIMIT_PREMIUM_PER_MINUTE=200 -RATE_LIMIT_ENTERPRISE_PER_MINUTE=1000 - -# Default rate limits -RATE_LIMIT_API_PER_MINUTE=100 -RATE_LIMIT_AUTH_PER_MINUTE=5 -RATE_LIMIT_EXPENSIVE_PER_MINUTE=10 -RATE_LIMIT_USER_PER_HOUR=1000 -``` - -## Rate Limit Headers - -The system adds comprehensive rate limit headers: - -- `X-RateLimit-Limit` - Current limit for the user/tier -- `X-RateLimit-Remaining` - Remaining requests in window -- `X-RateLimit-Reset` - Unix timestamp when limit resets -- `X-RateLimit-Window` - Window size in milliseconds -- `X-RateLimit-Tier` - User tier (if applicable) - -## API Endpoints - -### Rate Limiting Analytics - -```bash -GET /admin/rate-limiting/analytics?windowMs=3600000 -GET /admin/rate-limiting/tiered-limits -GET /admin/rate-limiting/configurations -``` - -### User Tier Management - -```bash -POST /admin/user-tiers/{userId}/tier -PUT /admin/user-tiers/{userId}/upgrade -PUT /admin/user-tiers/{userId}/downgrade -GET /admin/user-tiers/{userId}/tier -GET /admin/user-tiers/by-tier/{tier} -GET /admin/user-tiers/distribution -POST /admin/user-tiers/upgrade-request -POST /admin/user-tiers/{userId}/check-expiry -``` - -## Testing - -Run the comprehensive test suite: - -```bash -npm run test rate-limiting-enhancement.spec.ts -``` - -## Monitoring - -The enhanced rate limiting system provides: - -1. **Real-time Analytics**: Monitor current usage patterns -2. **Tier Distribution**: Track user tier adoption -3. **Block Rate Monitoring**: Identify abuse patterns -4. **Top User Tracking**: Identify heavy users - -## Best Practices - -1. **Use Tiered Rate Limiting**: Enable `useUserTier: true` for most endpoints -2. **Set Appropriate Limits**: Configure limits based on your infrastructure capacity -3. **Monitor Analytics**: Regularly check rate limiting analytics -4. **Audit Tier Changes**: Use metadata to track tier management decisions -5. **Handle Failures Gracefully**: The system fails open if Redis is unavailable - -## Migration from Basic Rate Limiting - -To migrate existing rate limiting: - -1. Replace `@Throttle()` decorators with `@TieredRateLimit()` -2. Update rate limit configurations in environment variables -3. Set up user tiers using the management API -4. Monitor analytics to ensure appropriate limits - -## Security Considerations - -1. **Rate Limit Bypass**: The system uses multiple identification methods (user ID, API key, IP) -2. **Redis Security**: Ensure Redis is properly secured and not exposed -3. **Tier Escalation**: Implement proper authorization for tier management endpoints -4. **Audit Trail**: Use metadata to track all tier changes - -## Performance - -- **Redis Storage**: Fast O(1) operations for rate limit checking -- **Minimal Overhead**: Efficient key generation and lookup -- **Batch Analytics**: Optimized analytics queries -- **Cleanup**: Automatic expiration of old rate limit data - -## Future Enhancements - -1. **Dynamic Limits**: AI-driven limit adjustment based on usage patterns -2. **Geographic Rate Limiting**: Region-specific rate limits -3. **Burst Handling**: Short-term burst capacity -4. **Advanced Analytics**: Machine learning for abuse detection -5. **Multi-tenant Support**: Organization-based rate limiting diff --git a/docs/health-checks.md b/docs/health-checks.md deleted file mode 100644 index 633247f1..00000000 --- a/docs/health-checks.md +++ /dev/null @@ -1,300 +0,0 @@ -# Health Check Implementation - -This document describes the comprehensive health check implementation for the PropChain-BackEnd application. - -## Overview - -The health check system provides detailed monitoring of all system components including database, Redis, blockchain services, system resources, and external dependencies. It includes analytics, scheduled checks, and manual triggering capabilities. - -## Endpoints - -### Basic Health Check -- **GET** `/health` -- **Description**: Basic health check for core services (database, Redis) -- **Response**: Health status of core services - -### Detailed Health Check -- **GET** `/health/detailed` -- **Description**: Comprehensive health check for all services -- **Response**: Health status of all services including database, Redis, blockchain, memory, CPU, disk, and dependencies - -### Comprehensive Health Check -- **GET** `/health/comprehensive` -- **Description**: Full health check with analytics and system information -- **Response**: Health status, analytics data, and detailed system information - -### Liveness Probe -- **GET** `/health/liveness` -- **Description**: Kubernetes liveness probe -- **Response**: Basic liveness information - -### Readiness Probe -- **GET** `/health/readiness` -- **Description**: Kubernetes readiness probe -- **Response**: Service readiness status - -### Health Analytics -- **GET** `/health/analytics` -- **Description**: Get health check analytics -- **Response**: Historical health check data and statistics - -### Clear Analytics -- **GET** `/health/analytics/clear` -- **Description**: Clear health check analytics -- **Response**: Confirmation message - -### Dependencies -- **GET** `/health/dependencies` -- **Description**: Get configured dependencies -- **Response**: List of monitored external dependencies - -### Manual Health Check Trigger -- **POST** `/health/trigger` -- **Description**: Trigger manual health check -- **Query Parameters**: - - `type`: `basic`, `detailed`, or `dependencies` (default: `basic`) -- **Response**: Health check results - -## Health Indicators - -### Database Health Indicator -- **Purpose**: Monitor database connectivity and performance -- **Checks**: Connection test, connection pool info, table count -- **Response Time**: Measured and reported -- **Error Handling**: Detailed error messages with response times - -### Redis Health Indicator -- **Purpose**: Monitor Redis connectivity and performance -- **Checks**: Ping test, read/write operations, server info, memory usage -- **Response Time**: Measured and reported -- **Details**: Connection info, memory stats, server version - -### Blockchain Health Indicator -- **Purpose**: Monitor blockchain RPC connectivity -- **Checks**: Block number, network info, gas prices, balance queries -- **Response Time**: Measured and reported -- **Details**: Network info, latest block data, gas information - -### Memory Health Indicator -- **Purpose**: Monitor system memory usage -- **Checks**: Heap usage, system memory, external memory -- **Threshold**: Unhealthy if heap usage > 80% -- **Details**: Memory usage breakdown and percentages - -### CPU Health Indicator -- **Purpose**: Monitor CPU usage and load -- **Checks**: Process CPU usage, system load average -- **Threshold**: Unhealthy if CPU > 90% or load average > 2x CPU count -- **Details**: CPU usage, load averages, system info - -### Disk Health Indicator -- **Purpose**: Monitor disk accessibility -- **Checks**: Write access test -- **Details**: Platform-specific disk information - -### Dependencies Health Indicator -- **Purpose**: Monitor external service dependencies -- **Checks**: HTTP health checks for configured dependencies -- **Configurable**: Dependencies can be added/removed via configuration -- **Details**: Response times, status codes, error information - -## Analytics - -The health check system collects and stores analytics data including: - -- Total health checks performed -- Success/failure rates -- Average response times -- Service-specific statistics -- Historical data (last 1000 metrics) - -### Analytics Features -- **Real-time tracking**: All health checks are recorded -- **Service-specific stats**: Individual metrics per service -- **Time-based filtering**: Query metrics by time range -- **Automatic cleanup**: Old metrics are pruned periodically - -## Scheduled Health Checks - -The system includes automated health checks: - -- **Every 5 minutes**: Basic health check (core services) -- **Every 30 minutes**: Extended health check (all services) -- **Every hour**: Dependency health check -- **Daily**: Metrics cleanup (midnight) - -## Configuration - -### Environment Variables - -```bash -# Database Configuration -DATABASE_URL=postgresql://user:password@localhost:5432/propchain - -# Redis Configuration -REDIS_HOST=localhost -REDIS_PORT=6379 -REDIS_PASSWORD=your_password -REDIS_DB=0 - -# Blockchain Configuration -RPC_URL=https://eth-mainnet.alchemyapi.io/v2/your_api_key - -# Health Check Dependencies (JSON array) -HEALTH_CHECK_DEPENDENCIES=[ - { - "name": "valuation-provider", - "url": "https://api.valuation-service.com/v1/health", - "timeout": 5000, - "method": "GET", - "expectedStatus": 200 - } -] -``` - -## Response Format - -### Healthy Response -```json -{ - "status": "ok", - "info": { - "database": { - "status": "up", - "details": { - "responseTime": "15ms", - "connectionPool": {...}, - "tableCount": 25, - "timestamp": "2024-01-01T00:00:00.000Z", - "message": "Database connection successful" - } - }, - "redis": { - "status": "up", - "details": { - "responseTime": "5ms", - "connection": {...}, - "memory": {...}, - "server": {...}, - "test": {...}, - "timestamp": "2024-01-01T00:00:00.000Z", - "message": "Redis connection successful" - } - } - }, - "details": { - "responseTime": "20ms" - } -} -``` - -### Unhealthy Response -```json -{ - "status": "error", - "error": "Database connection failed", - "details": { - "database": { - "status": "down", - "details": { - "error": "Connection timeout", - "responseTime": "5000ms", - "timestamp": "2024-01-01T00:00:00.000Z" - } - } - } -} -``` - -## Monitoring Integration - -### Kubernetes -- **Liveness Probe**: `/health/liveness` -- **Readiness Probe**: `/health/readiness` -- **Startup Probe**: `/health` (with appropriate configuration) - -### Prometheus Metrics -Health check metrics can be integrated with Prometheus using the existing `@willsoto/nestjs-prometheus` module. - -### Alerting -Configure alerts based on: -- Health check failures -- High response times -- Resource usage thresholds - -## Testing - -The health check system includes comprehensive tests: - -```bash -# Run health check tests -npm run test -- --testPathPattern=health - -# Run integration tests -npm run test:integration - -# Run e2e tests -npm run test:e2e -``` - -## Troubleshooting - -### Common Issues - -1. **Database Connection Failures** - - Check database connectivity - - Verify connection string - - Check connection pool settings - -2. **Redis Connection Failures** - - Verify Redis server is running - - Check connection parameters - - Verify authentication - -3. **Blockchain RPC Failures** - - Check RPC URL validity - - Verify API key if required - - Check network connectivity - -4. **High Memory Usage** - - Monitor memory leaks - - Check for memory-intensive operations - - Consider increasing memory limits - -5. **High CPU Usage** - - Profile CPU-intensive operations - - Check for infinite loops - - Optimize database queries - -### Debug Mode - -Enable debug logging by setting the log level: - -```bash -LOG_LEVEL=debug -``` - -This will provide detailed health check execution logs. - -## Performance Considerations - -- Health checks are designed to be lightweight -- Response times are measured and reported -- Timeouts are configured to prevent hanging -- Scheduled checks use appropriate intervals -- Metrics are limited to prevent memory issues - -## Security - -- Health check endpoints should be secured in production -- Consider IP whitelisting for health endpoints -- Rate limiting may be applied to prevent abuse -- Sensitive information is filtered from responses - -## Future Enhancements - -- Circuit breaker pattern implementation -- Advanced alerting integrations -- Performance benchmarking -- Distributed tracing integration -- Custom health check plugins diff --git a/docs/observability.md b/docs/observability.md deleted file mode 100644 index 474c860e..00000000 --- a/docs/observability.md +++ /dev/null @@ -1,374 +0,0 @@ -# Observability Features - -This document describes the comprehensive observability features implemented in the PropChain-BackEnd application. - -## Overview - -The observability system provides three main capabilities: -1. **Distributed Tracing** - Track requests across services and components -2. **Custom Metrics** - Monitor application performance and business metrics -3. **Performance Monitoring** - Real-time system and application health monitoring - -## Architecture - -### Components - -- **TracingService** - OpenTelemetry-based distributed tracing -- **MetricsInterceptor** - HTTP request/response metrics collection -- **PerformanceMonitorService** - System and application performance monitoring -- **ObservabilityController** - REST API for observability data -- **ObservabilityModule** - NestJS module that orchestrates all components - -## Features - -### 1. Distributed Tracing - -**Implementation**: OpenTelemetry with auto-instrumentation - -**Capabilities**: -- Automatic trace generation for HTTP requests -- Database query tracing -- Blockchain operation tracing -- Custom span creation -- Export to OTLP-compatible backends (Jaeger, Tempo, etc.) - -**Configuration**: -```bash -OTEL_SERVICE_NAME=propchain-backend -OTEL_SERVICE_VERSION=1.0.0 -OTEL_ENABLED=true -OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 -OTEL_SAMPLING_RATE=1.0 -``` - -**Usage**: -```typescript -// Create custom spans -const span = tracingService.createSpan('custom-operation', { - userId: '123', - operation: 'data-processing' -}); - -// Business logic here - -span.end(); -``` - -### 2. Custom Metrics - -**Implementation**: Prometheus with custom collectors - -**HTTP Metrics**: -- Request duration histogram -- Request count counter -- Request/response size histograms -- Active connections gauge -- Error rate tracking - -**Business Metrics**: -- Database query duration -- Blockchain operation duration -- Cache hit rates -- Custom application metrics - -**Available Endpoints**: -- `/metrics` - Prometheus metrics endpoint -- `/observability/metrics/current` - Current metrics snapshot -- `/observability/metrics/history` - Historical metrics data -- `/observability/metrics/average` - Average metrics over time - -**Example Metrics**: -``` -# HTTP request duration -http_request_duration_seconds{method="GET",route="/api/properties",status="200",user_id="123"} 0.245 - -# Database query duration -database_query_duration_seconds{operation="select",table="properties",query_type="find"} 0.012 - -# Blockchain operation duration -blockchain_operation_duration_seconds{operation="transfer",network="sepolia",contract="PropertyToken"} 2.456 -``` - -### 3. Performance Monitoring - -**Implementation**: Real-time system monitoring with alerts - -**Monitored Metrics**: -- CPU usage and load average -- Memory usage (used, free, total) -- Disk usage (when available) -- Network metrics (connections, request rate) -- Application metrics (uptime, error rate, response time) - -**Health Assessment**: -- **Healthy**: All metrics within normal thresholds -- **Warning**: 1-2 metrics exceed thresholds -- **Critical**: 3+ metrics exceed thresholds - -**Alert Thresholds** (configurable): -- CPU usage > 90% -- Memory usage > 90% -- Error rate > 5% -- Response time > 5000ms - -**Endpoints**: -- `/observability/health` - Detailed health status -- `/observability/tracing/status` - Tracing service status - -## Configuration - -### Environment Variables - -```bash -# OpenTelemetry Tracing -OTEL_SERVICE_NAME=propchain-backend -OTEL_SERVICE_VERSION=1.0.0 -OTEL_ENABLED=true -OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 -OTEL_SAMPLING_RATE=1.0 - -# Metrics -METRICS_ENABLED=true -METRICS_PATH=/metrics -METRICS_PORT=9090 - -# Performance Monitoring -PERFORMANCE_MONITORING_ENABLED=true -PERFORMANCE_MONITORING_INTERVAL=30000 -PERFORMANCE_METRICS_RETENTION=86400000 - -# Alert Thresholds -CPU_ALERT_THRESHOLD=90 -MEMORY_ALERT_THRESHOLD=90 -ERROR_RATE_ALERT_THRESHOLD=5 -RESPONSE_TIME_ALERT_THRESHOLD=5000 - -# Logging -LOG_LEVEL=info -LOG_FORMAT=json -LOGGING_ENABLED=true -``` - -### Integration with Observability Backends - -#### Jaeger -```bash -# Start Jaeger -docker run -d \ - --name jaeger \ - -p 16686:16686 \ - -p 4317:4317 \ - jaegertracing/all-in-one:latest - -# Configure environment -OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 -``` - -#### Prometheus -```yaml -# prometheus.yml -scrape_configs: - - job_name: 'propchain-backend' - static_configs: - - targets: ['localhost:3000'] - metrics_path: '/metrics' - scrape_interval: 30s -``` - -#### Grafana Dashboard -Import the provided Grafana dashboard configuration for visualization: -- CPU and Memory usage -- Request rates and response times -- Error rates and status codes -- Database and blockchain operation metrics - -## Usage Examples - -### Adding Custom Metrics - -```typescript -@Injectable() -export class PropertyService { - constructor(private metricsInterceptor: MetricsInterceptor) {} - - async createProperty(data: CreatePropertyDto) { - const start = Date.now(); - - try { - // Business logic - const property = await this.repository.create(data); - - // Record success metric - this.metricsInterceptor.recordCustomMetric( - 'property_creation_duration_seconds', - (Date.now() - start) / 1000, - { status: 'success' } - ); - - return property; - } catch (error) { - // Record error metric - this.metricsInterceptor.recordCustomMetric( - 'property_creation_duration_seconds', - (Date.now() - start) / 1000, - { status: 'error', error_type: error.constructor.name } - ); - throw error; - } - } -} -``` - -### Adding Custom Spans - -```typescript -@Injectable() -export class BlockchainService { - constructor(private tracingService: TracingService) {} - - async transferProperty(from: string, to: string, propertyId: string) { - const span = this.tracingService.createSpan('property-transfer', { - from, - to, - propertyId, - network: process.env.BLOCKCHAIN_NETWORK, - }); - - try { - // Blockchain operation - const result = await this.contract.transfer(from, to, propertyId); - - span.setAttributes({ - transactionHash: result.hash, - gasUsed: result.gasUsed.toString(), - }); - - return result; - } catch (error) { - span.recordException(error); - throw error; - } finally { - span.end(); - } - } -} -``` - -### Performance Monitoring Integration - -```typescript -@Controller() -export class AppController { - constructor(private performanceMonitor: PerformanceMonitorService) {} - - @Get('health') - getHealth() { - return this.performanceMonitor.getHealthStatus(); - } - - @Post('api/properties') - async createProperty(@Body() data: CreatePropertyDto) { - // Record request for rate calculation - this.performanceMonitor.recordRequest('/api/properties'); - - try { - return await this.propertyService.create(data); - } catch (error) { - // Record error for monitoring - this.performanceMonitor.recordError('/api/properties', error); - throw error; - } - } -} -``` - -## Best Practices - -### 1. Instrumentation -- Use auto-instrumentation for standard operations -- Add custom spans for business-critical operations -- Include relevant attributes in spans -- Use semantic conventions where possible - -### 2. Metrics -- Use meaningful metric names -- Include relevant labels for filtering -- Choose appropriate bucket sizes for histograms -- Avoid high cardinality labels - -### 3. Performance Monitoring -- Set appropriate alert thresholds -- Monitor trends over time -- Correlate metrics with business events -- Regularly review and adjust monitoring - -### 4. Security -- Secure metrics endpoints in production -- Use authentication for sensitive observability data -- Sanitize sensitive data from traces and metrics -- Follow data retention policies - -## Troubleshooting - -### Common Issues - -1. **Metrics not appearing** - - Check METRICS_ENABLED=true - - Verify metrics endpoint is accessible - - Check Prometheus configuration - -2. **Traces not exported** - - Verify OTEL_EXPORTER_OTLP_ENDPOINT - - Check network connectivity to collector - - Verify collector is running - -3. **High memory usage** - - Adjust PERFORMANCE_METRICS_RETENTION - - Check for metric cardinality issues - - Monitor garbage collection - -4. **Performance impact** - - Adjust OTEL_SAMPLING_RATE - - Use batch processors in production - - Monitor overhead - -### Debug Commands - -```bash -# Check metrics endpoint -curl http://localhost:3000/metrics - -# Check health status -curl http://localhost:3000/observability/health - -# Check tracing status -curl http://localhost:3000/observability/tracing/status - -# View current metrics -curl http://localhost:3000/observability/metrics/current -``` - -## Migration Guide - -### From Basic Logging -1. Install observability dependencies -2. Update environment configuration -3. Add observability module to app module -4. Replace manual logging with structured tracing -5. Add custom metrics for business operations - -### From Basic Metrics -1. Migrate existing Prometheus metrics -2. Add business-specific metrics -3. Implement performance monitoring -4. Set up alerting rules -5. Create dashboards - -## Future Enhancements - -- SLA monitoring and reporting -- Anomaly detection -- Distributed context propagation -- Custom alerting integrations -- Performance profiling integration -- Business intelligence metrics diff --git a/docs/properties-api.md b/docs/properties-api.md deleted file mode 100644 index 35541021..00000000 --- a/docs/properties-api.md +++ /dev/null @@ -1,189 +0,0 @@ -# Properties API Documentation - -## Overview - -The Properties API provides endpoints for managing real estate properties with advanced filtering, search, and pagination capabilities. - -## Endpoints - -### Get All Properties - -``` -GET /properties -``` - -#### Query Parameters - -| Parameter | Type | Description | Example | -| -------------- | ------ | -------------------------------------- | ------------------- | -| `page` | number | Page number (default: 1) | `?page=1` | -| `limit` | number | Items per page (default: 20, max: 100) | `?limit=20` | -| `sortBy` | string | Field to sort by | `?sortBy=price` | -| `sortOrder` | string | Sort direction: 'asc' or 'desc' | `?sortOrder=asc` | -| `search` | string | Search in title, description, location | `?search=apartment` | -| `type` | string | Filter by property type | `?type=RESIDENTIAL` | -| `status` | string | Filter by status | `?status=AVAILABLE` | -| `city` | string | Filter by city | `?city=New%20York` | -| `country` | string | Filter by country | `?country=USA` | -| `minPrice` | number | Minimum price | `?minPrice=100000` | -| `maxPrice` | number | Maximum price | `?maxPrice=500000` | -| `minBedrooms` | number | Minimum bedrooms | `?minBedrooms=2` | -| `maxBedrooms` | number | Maximum bedrooms | `?maxBedrooms=5` | -| `minBathrooms` | number | Minimum bathrooms | `?minBathrooms=1` | -| `maxBathrooms` | number | Maximum bathrooms | `?maxBathrooms=3` | -| `minArea` | number | Minimum square footage | `?minArea=500` | -| `maxArea` | number | Maximum square footage | `?maxArea=5000` | -| `ownerId` | string | Filter by owner ID | `?ownerId=user_123` | - -#### Property Types - -- `RESIDENTIAL` - Residential properties -- `COMMERCIAL` - Commercial properties -- `INDUSTRIAL` - Industrial properties -- `LAND` - Land parcels - -#### Property Status - -- `AVAILABLE` - Available for sale/rent -- `PENDING` - Under contract -- `SOLD` - Sold -- `RENTED` - Rented - -#### Example Requests - -**Basic filtering:** - -``` -GET /properties?type=RESIDENTIAL&status=AVAILABLE -``` - -**Price range filter:** - -``` -GET /properties?minPrice=100000&maxPrice=500000 -``` - -**Multiple filters:** - -``` -GET /properties?type=RESIDENTIAL&minBedrooms=2&maxBathrooms=3&minArea=1000 -``` - -**Search with pagination:** - -``` -GET /properties?search=apartment&page=1&limit=10&sortBy=price&sortOrder=desc -``` - -**City and country combined:** - -``` -GET /properties?city=New%20York&country=USA -``` - -#### Response Format - -```json -{ - "properties": [ - { - "id": "prop_123", - "title": "Luxury Downtown Apartment", - "description": "Beautiful 2-bedroom apartment", - "location": "New York, USA", - "price": 500000, - "status": "AVAILABLE", - "propertyType": "RESIDENTIAL", - "bedrooms": 2, - "bathrooms": 2, - "squareFootage": 1200, - "ownerId": "user_123" - } - ], - "total": 100, - "page": 1, - "limit": 20, - "totalPages": 5 -} -``` - -### Get Property by ID - -``` -GET /properties/:id -``` - -### Create Property - -``` -POST /properties -``` - -### Update Property - -``` -PATCH /properties/:id -``` - -### Update Property Status - -``` -PATCH /properties/:id/status -``` - -### Delete Property - -``` -DELETE /properties/:id -``` - -### Get Properties by Owner - -``` -GET /properties/owner/:ownerId -``` - -### Get Property Statistics - -``` -GET /properties/statistics -``` - -### Search Nearby Properties - -``` -GET /properties/search/nearby?latitude=40.7128&longitude=-74.006&radiusKm=10 -``` - -## Filtering Features - -### Combined City and Country Filter - -The city and country filters are combined into a single location search. For example: - -- `?city=New York&country=USA` will search for properties with "New York, USA" in the location field - -### Range Filters - -All numeric filters support range queries: - -- `minX` - Minimum value (inclusive) -- `maxX` - Maximum value (inclusive) - -### Search - -The search parameter performs case-insensitive matching across: - -- Property title -- Property description -- Property location - -## Error Handling - -All endpoints return standard HTTP status codes: - -- `200` - Success -- `400` - Bad Request (invalid parameters) -- `401` - Unauthorized -- `404` - Not Found -- `500` - Internal Server Error diff --git a/docs/testing.md b/docs/testing.md deleted file mode 100644 index 7f5fb6bb..00000000 --- a/docs/testing.md +++ /dev/null @@ -1,301 +0,0 @@ -# Advanced API Testing and Quality Assurance - -This document describes the comprehensive API testing and quality assurance system implemented for the PropChain backend. - -## Overview - -The testing system provides: -- **Automated API test generation** from OpenAPI specifications -- **Contract testing framework** for provider-consumer contract verification -- **Performance benchmarking** with load testing, stress testing, and spike testing -- **Test data management** with realistic mock data generation -- **Scheduled test execution** with comprehensive reporting - -## Architecture - -### Core Components - -1. **TestGenerator** (`src/testing/TestGenerator.ts`) - - Generates automated tests from OpenAPI/Swagger specifications - - Supports multiple mock data strategies (random, realistic, minimal) - - Creates unit, integration, and performance tests - - Generates contract tests based on API schemas - -2. **ContractTester** (`src/testing/ContractTester.ts`) - - Implements contract testing framework similar to Pact - - Supports contract generation from OpenAPI specs - - Validates provider-consumer contracts - - Provides contract verification and publishing - -3. **PerformanceBenchmark** (`src/testing/PerformanceBenchmark.ts`) - - Comprehensive performance testing capabilities - - Load testing, stress testing, spike testing, endurance testing - - Real-time metrics and percentile calculations - - Performance threshold validation - -4. **TestingService** (`src/services/TestingService.ts`) - - Main orchestration service - - Manages test suites and execution - - Provides scheduled testing capabilities - - Generates comprehensive reports - -## Usage - -### Creating a Test Suite - -```typescript -const testSuite: TestingSuiteConfig = { - name: 'api-comprehensive-tests', - description: 'Comprehensive API testing suite', - testGeneration: { - includeNegativeTests: true, - includeEdgeCases: true, - includePerformanceTests: true, - mockDataStrategy: 'realistic' - }, - contractTesting: { - enabled: true, - contractsPath: 'contracts', - verificationOptions: { - timeout: 30000, - retries: 3, - allowExtraResponseFields: false - } - }, - performanceTesting: { - enabled: true, - endpoints: [ - { - name: 'get-properties', - method: 'GET', - url: 'http://localhost:3000/api/v1/properties', - weight: 3 - }, - { - name: 'create-property', - method: 'POST', - url: 'http://localhost:3000/api/v1/properties', - weight: 1 - } - ], - thresholds: { - maxResponseTime: 1000, - minRequestsPerSecond: 100, - maxErrorRate: 1 - }, - config: { - duration: 300, - concurrency: 20, - rampUpTime: 30 - } - }, - schedule: { - enabled: true, - cronExpression: '0 2 * * *' // Daily at 2 AM - } -}; -``` - -### Executing Tests - -```typescript -// Execute a test suite -const result = await testingService.executeTestSuite('api-comprehensive-tests'); - -// Run health check -const health = await testingService.runHealthCheck(); - -// Generate comprehensive report -const report = await testingService.generateComprehensiveReport(); -``` - -## API Endpoints - -### Test Suite Management -- `POST /api/v1/testing/suites` - Create test suite -- `GET /api/v1/testing/suites` - List all test suites -- `GET /api/v1/testing/suites/:name` - Get specific test suite -- `PUT /api/v1/testing/suites/:name` - Update test suite -- `DELETE /api/v1/testing/suites/:name` - Delete test suite - -### Test Execution -- `POST /api/v1/testing/suites/:name/execute` - Execute test suite -- `GET /api/v1/testing/executions` - Get execution history -- `GET /api/v1/testing/executions/:id` - Get execution report - -### Health and Reporting -- `GET /api/v1/testing/health` - Run health check -- `GET /api/v1/testing/report/comprehensive` - Generate comprehensive report - -## Configuration - -### Environment Variables - -```bash -# API Configuration -API_BASE_URL=http://localhost:3000 - -# Contract Testing -CONTRACT_REGISTRY_URL=http://localhost:8080 - -# Performance Testing -DEFAULT_TIMEOUT=30000 -DEFAULT_CONCURRENCY=10 -DEFAULT_DURATION=60 -``` - -## Test Types - -### 1. Automated Test Generation - -The system can generate tests automatically from your OpenAPI specification: - -- **Unit Tests**: Test individual endpoints with various inputs -- **Integration Tests**: Test endpoint interactions and workflows -- **Negative Tests**: Test error conditions and edge cases -- **Performance Tests**: Basic performance benchmarks - -### 2. Contract Testing - -Contract testing ensures that your API contracts are maintained between providers and consumers: - -- **Contract Generation**: Auto-generate contracts from OpenAPI specs -- **Contract Verification**: Verify provider compliance with contracts -- **Contract Publishing**: Publish contracts to a registry -- **Schema Validation**: Validate request/response schemas - -### 3. Performance Testing - -Comprehensive performance testing capabilities: - -- **Load Testing**: Test under normal and peak load conditions -- **Stress Testing**: Test system limits and breaking points -- **Spike Testing**: Test response to sudden load increases -- **Endurance Testing**: Test performance over extended periods -- **Threshold Validation**: Validate against performance SLAs - -## Reports and Analytics - -### Test Reports - -The system generates detailed reports including: - -- **Execution Summary**: Pass/fail rates, duration, test counts -- **Performance Metrics**: Response times, throughput, percentiles -- **Error Analysis**: Error rates, error types, failure patterns -- **Trend Analysis**: Performance trends over time -- **Recommendations**: Automated recommendations based on results - -### Report Formats - -- **JSON**: Machine-readable reports for CI/CD integration -- **Markdown**: Human-readable reports for documentation -- **HTML**: Interactive reports with charts and graphs -- **JUnit**: XML reports for test result aggregation - -## Integration with CI/CD - -### GitHub Actions Example - -```yaml -name: API Testing -on: [push, pull_request] - -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Setup Node.js - uses: actions/setup-node@v2 - with: - node-version: '18' - - name: Install dependencies - run: npm ci - - name: Run comprehensive tests - run: npm run test:comprehensive - - name: Upload test reports - uses: actions/upload-artifact@v2 - with: - name: test-reports - path: test-reports/ -``` - -### Package.json Scripts - -```json -{ - "scripts": { - "test:comprehensive": "ts-node scripts/run-comprehensive-tests.ts", - "test:contracts": "npm run test:contracts", - "test:performance": "npm run test:performance", - "test:load": "npm run test:load", - "test:stress": "npm run test:stress" - } -} -``` - -## Best Practices - -### 1. Test Suite Organization -- Create separate suites for different testing needs -- Use descriptive names and descriptions -- Configure appropriate scheduling for each suite - -### 2. Performance Testing -- Start with low concurrency and gradually increase -- Set realistic thresholds based on SLAs -- Monitor system resources during tests - -### 3. Contract Testing -- Generate contracts from your OpenAPI specification -- Verify contracts in CI/CD pipeline -- Keep contracts in version control - -### 4. Test Data Management -- Use realistic mock data for better test coverage -- Separate test data from production data -- Clean up test data after execution - -## Troubleshooting - -### Common Issues - -1. **Test Generation Fails** - - Check OpenAPI specification validity - - Verify API server is running - - Check network connectivity - -2. **Contract Verification Fails** - - Verify provider URL is accessible - - Check contract format and content - - Review verification options - -3. **Performance Test Issues** - - Monitor system resources - - Check timeout configurations - - Verify endpoint availability - -### Debug Mode - -Enable debug logging by setting: -```bash -LOG_LEVEL=debug -``` - -## Future Enhancements - -Planned improvements include: - -- **Visual Test Reports**: Interactive dashboards and charts -- **AI-Powered Test Generation**: ML-based test case generation -- **Distributed Testing**: Support for multi-region testing -- **Real-time Monitoring**: Live performance monitoring -- **Integration Monitoring**: External service dependency testing - -## Support - -For questions or issues: -- Check the logs in the `test-reports` directory -- Review the generated reports for detailed error information -- Consult the API documentation for endpoint details diff --git a/docs/valuation-api.md b/docs/valuation-api.md deleted file mode 100644 index 54e528fa..00000000 --- a/docs/valuation-api.md +++ /dev/null @@ -1,250 +0,0 @@ -# Property Valuation API Documentation - -## Overview - -The Property Valuation API provides automated property value estimates based on market data, location, and property features. It integrates with external ML services and valuation APIs to provide accurate property valuations. - -## Endpoints - -### Get Property Valuation - -``` -POST /valuation/:propertyId -``` - -#### Description - -Gets a property valuation based on its features and external market data. - -#### Parameters - -- `propertyId` (path): The ID of the property to value - -#### Request Body - -```json -{ - "location": "123 Main St, City, State", - "bedrooms": 3, - "bathrooms": 2, - "squareFootage": 1500, - "yearBuilt": 1995, - "propertyType": "single-family", - "lotSize": 0.25 -} -``` - -#### Response - -```json -{ - "propertyId": "property-id-string", - "estimatedValue": 500000, - "confidenceScore": 0.85, - "valuationDate": "2023-12-01T10:00:00.000Z", - "source": "combined", - "marketTrend": "upward", - "featuresUsed": { - "location": "123 Main St, City, State", - "bedrooms": 3, - "bathrooms": 2, - "squareFootage": 1500, - "yearBuilt": 1995, - "propertyType": "single-family", - "lotSize": 0.25 - }, - "rawData": { - "sources": [ - { - "source": "zillow", - "value": 510000 - }, - { - "source": "redfin", - "value": 495000 - } - ] - } -} -``` - -### Get Property Valuation History - -``` -GET /valuation/:propertyId/history -``` - -#### Description - -Retrieves the historical valuations for a specific property. - -#### Parameters - -- `propertyId` (path): The ID of the property - -#### Response - -```json -[ - { - "propertyId": "property-id-string", - "estimatedValue": 500000, - "confidenceScore": 0.85, - "valuationDate": "2023-12-01T10:00:00.000Z", - "source": "combined", - "marketTrend": "upward" - }, - { - "propertyId": "property-id-string", - "estimatedValue": 495000, - "confidenceScore": 0.82, - "valuationDate": "2023-11-01T10:00:00.000Z", - "source": "combined", - "marketTrend": "upward" - } -] -``` - -### Get Market Trend Analysis - -``` -GET /valuation/trends/:location -``` - -#### Description - -Retrieves market trend analysis for a specific location. - -#### Parameters - -- `location` (path): The location to analyze - -#### Response - -```json -{ - "location": "New York, NY", - "trendData": [ - { - "date": "2023-11-01T00:00:00.000Z", - "avgValue": 750000 - }, - { - "date": "2023-12-01T00:00:00.000Z", - "avgValue": 765000 - } - ], - "trendDirection": "upward" -} -``` - -### Get Latest Valuation - -``` -GET /valuation/:propertyId/latest -``` - -#### Description - -Retrieves the most recent valuation for a property. - -#### Parameters - -- `propertyId` (path): The ID of the property - -#### Response - -Same as Get Property Valuation endpoint. - -### Batch Valuations - -``` -POST /valuation/batch -``` - -#### Description - -Get valuations for multiple properties in a single request. - -#### Request Body - -```json -{ - "properties": [ - { - "propertyId": "property-1", - "features": { - "location": "123 Main St, City, State", - "bedrooms": 3, - "bathrooms": 2, - "squareFootage": 1500 - } - }, - { - "propertyId": "property-2", - "features": { - "location": "456 Oak Ave, City, State", - "bedrooms": 4, - "bathrooms": 3, - "squareFootage": 2000 - } - } - ] -} -``` - -#### Response - -```json -[ - { - "propertyId": "property-1", - "valuation": { - "propertyId": "property-1", - "estimatedValue": 500000, - "confidenceScore": 0.85, - "valuationDate": "2023-12-01T10:00:00.000Z", - "source": "combined", - "marketTrend": "upward" - }, - "status": "success" - }, - { - "propertyId": "property-2", - "error": "Property not found", - "status": "error" - } -] -``` - -## Features - -### Integration with External APIs - -- Zillow API for property valuations -- Redfin API for comparative market analysis -- CoreLogic API for comprehensive property data - -### Valuation Confidence Scoring - -The API provides confidence scores for each valuation, indicating the reliability of the estimate based on data quality and availability. - -### Historical Tracking - -All valuations are stored with timestamps, allowing for trend analysis and comparison over time. - -### Market Trend Analysis - -The API analyzes market trends in specific locations to provide context for individual property valuations. - -### Caching Strategy - -Valuation results are cached to reduce API calls to external services and improve response times. - -### Error Handling - -Comprehensive error handling for API failures, with fallback mechanisms and graceful degradation. - -### Rate Limiting - -Built-in rate limiting to prevent abuse of external valuation APIs. diff --git a/eslint.config.js b/eslint.config.js deleted file mode 100644 index 3c1adbaf..00000000 --- a/eslint.config.js +++ /dev/null @@ -1,29 +0,0 @@ -import js from '@eslint/js'; -import tseslint from 'typescript-eslint'; -import prettierConfig from 'eslint-config-prettier'; -import prettierPlugin from 'eslint-plugin-prettier'; - -export default tseslint.config(js.configs.recommended, ...tseslint.configs.recommended, prettierConfig, { - plugins: { prettier: prettierPlugin }, - rules: { - // Prettier formatting as ESLint errors - 'prettier/prettier': 'error', - - // Naming conventions - '@typescript-eslint/naming-convention': [ - 'error', - { selector: 'variable', format: ['camelCase', 'UPPER_CASE'] }, - { selector: 'function', format: ['camelCase', 'PascalCase'] }, - { selector: 'typeLike', format: ['PascalCase'] }, // interfaces, types, classes - { selector: 'enumMember', format: ['UPPER_CASE'] }, - ], - - // General best practices - 'no-unused-vars': 'off', - '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }], - '@typescript-eslint/explicit-function-return-type': 'warn', - '@typescript-eslint/no-explicit-any': 'warn', - eqeqeq: ['error', 'always'], - 'no-console': 'warn', - }, -}); diff --git a/indexer-monitor.service.ts b/indexer-monitor.service.ts deleted file mode 100644 index 7633cbea..00000000 --- a/indexer-monitor.service.ts +++ /dev/null @@ -1,321 +0,0 @@ -/** - * @fileoverview Service to monitor blockchain indexer drift and failures. - * @issue #208 - */ - -import { Injectable, Logger } from '@nestjs/common'; -import { Cron, CronExpression } from '@nestjs/schedule'; -import { InjectMetric } from '@willsoto/nestjs-prometheus'; -import { Gauge, Counter } from 'prom-client'; -import { PrismaService } from '../database/prisma/prisma.service'; -import { BlockchainService } from '../blockchain/blockchain.service'; // Assuming a blockchain service exists - -export interface IndexerAlert { - id: string; - type: 'HIGH_DRIFT' | 'STALLED_INDEXER' | 'BLOCKCHAIN_UNAVAILABLE' | 'DATABASE_ERROR'; - severity: 'WARNING' | 'CRITICAL'; - message: string; - currentHeight?: number; - targetHeight?: number; - drift?: number; - timestamp: Date; - resolved: boolean; - resolvedAt?: Date; -} - -export interface IndexerMetrics { - currentHeight: number; - targetHeight: number; - drift: number; - lastCheckTime: Date; - isHealthy: boolean; - alertsCount: number; -} - -@Injectable() -export class IndexerMonitorService { - private readonly logger = new Logger(IndexerMonitorService.name); - private alerts: Map = new Map(); - private consecutiveFailures = 0; - private lastSuccessfulCheck?: Date; - private readonly maxConsecutiveFailures = 5; - private readonly criticalDriftThreshold = 50; - private readonly warningDriftThreshold = 10; - private readonly stalledThreshold = 5; // minutes - - constructor( - @InjectMetric('propchain_indexer_current_height') - private readonly currentHeightGauge: Gauge, - @InjectMetric('propchain_indexer_target_height') - private readonly targetHeightGauge: Gauge, - @InjectMetric('propchain_indexer_height_drift') - private readonly driftGauge: Gauge, - @InjectMetric('propchain_indexer_alerts_total') - private readonly alertsCounter: Counter, - @InjectMetric('propchain_indexer_health_status') - private readonly healthStatusGauge: Gauge, - @InjectMetric('propchain_indexer_consecutive_failures') - private readonly consecutiveFailuresGauge: Gauge, - @InjectMetric('propchain_indexer_last_check_timestamp') - private readonly lastCheckGauge: Gauge, - private readonly prisma: PrismaService, - private readonly blockchainService: BlockchainService, - ) { } - - @Cron(CronExpression.EVERY_MINUTE) - async checkIndexerDrift() { - this.logger.debug('Checking for indexer drift...'); - const checkStartTime = Date.now(); - - try { - const targetHeight = await this.blockchainService.getLatestBlockHeight(); - const lastIndexedBlock = await this.prisma.block.findFirst({ - orderBy: { height: 'desc' }, - }); - - const currentHeight = lastIndexedBlock?.height ?? 0; - const drift = targetHeight - currentHeight; - const now = new Date(); - - // Update Prometheus metrics - this.currentHeightGauge.set(currentHeight); - this.targetHeightGauge.set(targetHeight); - this.driftGauge.set(drift); - this.lastCheckGauge.set(now.getTime() / 1000); - - // Determine health status - const isHealthy = this.determineHealthStatus(drift, currentHeight); - this.healthStatusGauge.set(isHealthy ? 1 : 0); - - // Reset consecutive failures on success - this.consecutiveFailures = 0; - this.lastSuccessfulCheck = now; - this.consecutiveFailuresGauge.set(0); - - // Check for various failure scenarios - await this.checkForAlerts(currentHeight, targetHeight, drift, now); - - // Log appropriate level based on severity - if (drift > this.criticalDriftThreshold) { - this.logger.error( - `CRITICAL: High indexer drift detected! Drift is ${drift} blocks. (Current: ${currentHeight}, Target: ${targetHeight})`, - ); - } else if (drift > this.warningDriftThreshold) { - this.logger.warn( - `WARNING: Indexer drift detected! Drift is ${drift} blocks. (Current: ${currentHeight}, Target: ${targetHeight})`, - ); - } else { - this.logger.log( - `Indexer is healthy. Drift is ${drift} blocks. (Current: ${currentHeight}, Target: ${targetHeight})`, - ); - } - - // Check for stalled indexer - await this.checkForStalledIndexer(lastIndexedBlock?.createdAt, now); - - } catch (error) { - this.consecutiveFailures++; - this.consecutiveFailuresGauge.set(this.consecutiveFailures); - - this.logger.error(`Failed to check indexer drift (attempt ${this.consecutiveFailures}/${this.maxConsecutiveFailures})`, error.stack); - this.driftGauge.set(-1); // Use -1 to indicate a check failure - this.healthStatusGauge.set(0); - - // Create alert for consecutive failures - if (this.consecutiveFailures >= this.maxConsecutiveFailures) { - await this.createAlert({ - type: 'BLOCKCHAIN_UNAVAILABLE', - severity: 'CRITICAL', - message: `Indexer monitor has failed ${this.consecutiveFailures} consecutive times. Last error: ${error.message}`, - timestamp: new Date(), - }); - } - - // Create alert for database errors specifically - if (error.message?.includes('database') || error.message?.includes('prisma')) { - await this.createAlert({ - type: 'DATABASE_ERROR', - severity: 'CRITICAL', - message: `Database error during indexer check: ${error.message}`, - timestamp: new Date(), - }); - } - } - - // Clean up old resolved alerts - await this.cleanupOldAlerts(); - } - - private determineHealthStatus(drift: number, currentHeight: number): boolean { - if (drift > this.criticalDriftThreshold || currentHeight === 0) { - return false; - } - - if (this.consecutiveFailures > 0) { - return false; - } - - if (!this.lastSuccessfulCheck) { - return false; - } - - // Check if last successful check was too long ago - const timeSinceLastSuccess = Date.now() - this.lastSuccessfulCheck.getTime(); - const maxTimeWithoutSuccess = 10 * 60 * 1000; // 10 minutes - if (timeSinceLastSuccess > maxTimeWithoutSuccess) { - return false; - } - - return drift <= this.warningDriftThreshold; - } - - private async checkForAlerts(currentHeight: number, targetHeight: number, drift: number, timestamp: Date) { - // Check for high drift alert - if (drift > this.criticalDriftThreshold) { - await this.createAlert({ - type: 'HIGH_DRIFT', - severity: 'CRITICAL', - message: `Critical indexer drift: ${drift} blocks behind target`, - currentHeight, - targetHeight, - drift, - timestamp, - }); - } else if (drift > this.warningDriftThreshold) { - await this.createAlert({ - type: 'HIGH_DRIFT', - severity: 'WARNING', - message: `Warning: Indexer drift of ${drift} blocks detected`, - currentHeight, - targetHeight, - drift, - timestamp, - }); - } - - // Check for stalled indexer (no new blocks for a long time) - if (currentHeight > 0 && drift === 0) { - // If drift is 0 but we haven't seen new blocks, check if indexer is stalled - const lastIndexedBlock = await this.prisma.block.findFirst({ - orderBy: { height: 'desc' }, - }); - - if (lastIndexedBlock?.createdAt) { - await this.checkForStalledIndexer(lastIndexedBlock.createdAt, timestamp); - } - } - } - - private async checkForStalledIndexer(lastBlockTime?: Date, currentTime = new Date()) { - if (!lastBlockTime) { - return; - } - - const timeSinceLastBlock = currentTime.getTime() - lastBlockTime.getTime(); - const stalledThresholdMs = this.stalledThreshold * 60 * 1000; - - if (timeSinceLastBlock > stalledThresholdMs) { - const stalledMinutes = Math.floor(timeSinceLastBlock / (60 * 1000)); - await this.createAlert({ - type: 'STALLED_INDEXER', - severity: 'WARNING', - message: `Indexer appears stalled - no new blocks for ${stalledMinutes} minutes`, - timestamp: currentTime, - }); - } - } - - private async createAlert(alert: Omit) { - const alertId = `${alert.type}_${Date.now()}`; - const fullAlert: IndexerAlert = { - ...alert, - id: alertId, - resolved: false, - }; - - // Check if similar alert already exists and is unresolved - const existingAlert = Array.from(this.alerts.values()).find( - a => a.type === alert.type && !a.resolved - ); - - if (existingAlert) { - // Update existing alert instead of creating duplicate - existingAlert.message = alert.message; - existingAlert.timestamp = alert.timestamp; - existingAlert.currentHeight = alert.currentHeight; - existingAlert.targetHeight = alert.targetHeight; - existingAlert.drift = alert.drift; - return; - } - - this.alerts.set(alertId, fullAlert); - this.alertsCounter.inc({ type: alert.type, severity: alert.severity }); - - this.logger.warn(`Indexer alert created: ${alert.type} - ${alert.message}`, { - alertId, - type: alert.type, - severity: alert.severity, - currentHeight: alert.currentHeight, - targetHeight: alert.targetHeight, - drift: alert.drift, - }); - } - - private async cleanupOldAlerts() { - const now = new Date(); - const cleanupThreshold = 24 * 60 * 60 * 1000; // 24 hours - - for (const [alertId, alert] of this.alerts.entries()) { - if (alert.resolved && (now.getTime() - alert.resolvedAt!.getTime() > cleanupThreshold)) { - this.alerts.delete(alertId); - } - } - } - - // Public methods for external access - async getMetrics(): Promise { - const lastIndexedBlock = await this.prisma.block.findFirst({ - orderBy: { height: 'desc' }, - }); - - const currentHeight = lastIndexedBlock?.height ?? 0; - const targetHeight = await this.blockchainService.getLatestBlockHeight().catch(() => 0); - const drift = targetHeight - currentHeight; - const isHealthy = this.determineHealthStatus(drift, currentHeight); - - return { - currentHeight, - targetHeight, - drift, - lastCheckTime: this.lastSuccessfulCheck || new Date(), - isHealthy, - alertsCount: Array.from(this.alerts.values()).filter(a => !a.resolved).length, - }; - } - - async getActiveAlerts(): Promise { - return Array.from(this.alerts.values()).filter(alert => !alert.resolved); - } - - async resolveAlert(alertId: string): Promise { - const alert = this.alerts.get(alertId); - if (alert && !alert.resolved) { - alert.resolved = true; - alert.resolvedAt = new Date(); - this.logger.log(`Indexer alert resolved: ${alertId}`); - return true; - } - return false; - } - - async getHealthStatus(): Promise<{ healthy: boolean; details: IndexerMetrics; alerts: IndexerAlert[] }> { - const metrics = await this.getMetrics(); - const alerts = await this.getActiveAlerts(); - - return { - healthy: metrics.isHealthy && alerts.length === 0, - details: metrics, - alerts, - }; - } -} \ No newline at end of file diff --git a/jest.config.js b/jest.config.js index 0e27d94f..eaef2437 100644 --- a/jest.config.js +++ b/jest.config.js @@ -3,49 +3,13 @@ module.exports = { rootDir: '.', testRegex: '.*\\.spec\\.ts$', transform: { - '^.+\\.(t|j)s$': [ - 'ts-jest', - { - tsconfig: 'tsconfig.spec.json', - }, - ], + '^.+\\.(t|j)s$': 'ts-jest', }, collectCoverageFrom: [ 'src/**/*.(t|j)s', - '!src/**/*.interface.ts', - '!src/**/*.dto.ts', - '!src/**/*.config.ts', - '!src/**/*.module.ts', - '!src/main.ts', - '!src/**/*.mock.ts', ], coverageDirectory: 'coverage', - coverageReporters: ['text', 'lcov', 'html', 'json'], - coverageThreshold: { - global: { - branches: 28, - functions: 35, - lines: 35, - statements: 35, - }, - }, testEnvironment: 'node', - roots: ['/test/'], - moduleNameMapper: { - '^src/(.*)$': '/src/$1', - }, - testPathIgnorePatterns: [ - '/node_modules/', - '/dist/', - '/test/database/', - 'e2e-spec.ts', - 'error_consistency.spec.ts', - 'api-keys.pagination.spec.ts', - ], - setupFilesAfterEnv: ['/test/setup.ts'], testTimeout: 30000, - verbose: true, - detectOpenHandles: true, - forceExit: true, - maxWorkers: '50%', + passWithNoTests: true, }; diff --git a/junit.xml b/junit.xml deleted file mode 100644 index 3340d2f7..00000000 --- a/junit.xml +++ /dev/null @@ -1,953 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/loadtests/propchain-loadtest.js b/loadtests/propchain-loadtest.js deleted file mode 100644 index 2a880cce..00000000 --- a/loadtests/propchain-loadtest.js +++ /dev/null @@ -1,24 +0,0 @@ -import http from 'k6/http'; -import { check, sleep } from 'k6'; - -export const options = { - vus: 5, - duration: '10s', - thresholds: { - http_req_failed: ['rate<0.01'], - http_req_duration: ['p(95)<1000'], - }, -}; - -const API_URL = (__ENV.API_URL || 'http://localhost:3000').replace(/\/+$/, ''); -const configuredHealthPath = __ENV.HEALTH_PATH || '/api/v1/health/liveness'; -const HEALTH_PATH = configuredHealthPath.startsWith('/') ? configuredHealthPath : `/${configuredHealthPath}`; - -export default function () { - const res = http.get(`${API_URL}${HEALTH_PATH}`); - check(res, { - 'health status is 200': r => r.status === 200, - }); - sleep(1); -} - diff --git a/monitoring.module.ts b/monitoring.module.ts deleted file mode 100644 index 08f079d0..00000000 --- a/monitoring.module.ts +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @fileoverview Module for application monitoring tasks, like indexer health. - * @issue #208 - */ - -import { Module } from '@nestjs/common'; -import { ScheduleModule } from '@nestjs/schedule'; -import { makeGaugeProvider, makeCounterProvider } from '@willsoto/nestjs-prometheus'; -import { IndexerMonitorService } from './indexer-monitor.service'; -import { IndexerMonitorController } from './src/monitoring/indexer-monitor.controller'; -import { PrismaModule } from '../src/database/prisma/prisma.module'; -import { BlockchainModule } from '../src/blockchain/blockchain.module'; - -@Module({ - imports: [ScheduleModule.forRoot(), PrismaModule, BlockchainModule], - controllers: [IndexerMonitorController], - providers: [ - IndexerMonitorService, - makeGaugeProvider({ - name: 'propchain_indexer_current_height', - help: 'The latest block height processed by the indexer.', - }), - makeGaugeProvider({ - name: 'propchain_indexer_target_height', - help: 'The current latest block height on the blockchain.', - }), - makeGaugeProvider({ - name: 'propchain_indexer_height_drift', - help: 'The difference between target and current indexer height.', - }), - makeCounterProvider({ - name: 'propchain_indexer_alerts_total', - help: 'Total number of indexer alerts generated.', - labelNames: ['type', 'severity'], - }), - makeGaugeProvider({ - name: 'propchain_indexer_health_status', - help: 'Health status of the indexer (1 = healthy, 0 = unhealthy).', - }), - makeGaugeProvider({ - name: 'propchain_indexer_consecutive_failures', - help: 'Number of consecutive failures in indexer monitoring.', - }), - makeGaugeProvider({ - name: 'propchain_indexer_last_check_timestamp', - help: 'Timestamp of the last indexer health check.', - }), - ], - exports: [IndexerMonitorService], -}) -export class MonitoringModule { } \ No newline at end of file diff --git a/nest-cli.json b/nest-cli.json index 9318e745..f9aa683b 100644 --- a/nest-cli.json +++ b/nest-cli.json @@ -3,37 +3,6 @@ "collection": "@nestjs/schematics", "sourceRoot": "src", "compilerOptions": { - "deleteOutDir": true, - "watchAssets": true, - "assets": ["**/*.json", "**/*.proto", "**/*.hbs"], - "plugins": [ - { - "name": "@nestjs/swagger", - "options": { - "classValidatorShim": true, - "introspectComments": true - } - } - ] - }, - "projects": { - "app": { - "type": "application", - "root": "src", - "entryFile": "main", - "sourceRoot": "src", - "compilerOptions": { - "tsConfigPath": "tsconfig.app.json" - } - }, - "test": { - "type": "library", - "root": "test", - "entryFile": "index", - "sourceRoot": "test", - "compilerOptions": { - "tsConfigPath": "tsconfig.spec.json" - } - } + "deleteOutDir": true } } diff --git a/package-lock.json b/package-lock.json index bb42e992..48b8612a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,119 +9,45 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@liaoliaots/nestjs-redis": "^10.0.0", - "@nestjs/bull": "^10.0.1", - "@nestjs/cache-manager": "^3.1.0", "@nestjs/common": "^10.3.0", "@nestjs/config": "^3.1.1", "@nestjs/core": "^10.3.0", - "@nestjs/jwt": "^11.0.2", - "@nestjs/passport": "^10.0.3", "@nestjs/platform-express": "^10.3.0", - "@nestjs/schedule": "^4.0.0", - "@nestjs/swagger": "^7.2.0", - "@nestjs/terminus": "^10.3.0", - "@nestjs/throttler": "^5.1.1", - "@nestjs/typeorm": "^10.0.2", - "@nomicfoundation/hardhat-toolbox": "^4.0.0", - "@opentelemetry/auto-instrumentations-node": "^0.70.1", - "@opentelemetry/resources": "^2.5.1", - "@opentelemetry/sdk-node": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.39.0", "@prisma/client": "^6.19.2", - "@types/nodemailer": "^7.0.11", - "@willsoto/nestjs-prometheus": "^6.0.2", - "axios": "^1.6.2", "bcrypt": "^6.0.0", - "bull": "^4.12.2", - "cache-manager": "^7.2.8", - "cache-manager-ioredis-yet": "^2.1.2", - "cache-manager-redis-store": "^3.0.1", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", - "cls-hooked": "^4.2.2", - "compression": "^1.7.4", - "cors": "^2.8.5", - "crypto-js": "^4.2.0", - "csv-parser": "^3.0.0", "dotenv": "^16.3.1", - "ethers": "^6.9.0", - "express-rate-limit": "^7.1.5", - "hardhat": "^2.19.4", - "helmet": "^7.1.0", - "ioredis": "^5.3.2", - "joi": "^17.11.0", "jsonwebtoken": "^9.0.2", - "lodash": "^4.17.21", - "mapped-types": "^0.0.1", - "moment": "^2.29.4", - "multer": "^2.0.2", - "nest-winston": "^1.10.2", - "nestjs-i18n": "^10.4.0", - "nodemailer": "^8.0.3", - "opossum": "^9.0.0", "passport": "^0.7.0", - "passport-custom": "^1.1.1", "passport-jwt": "^4.0.1", - "passport-local": "^1.0.0", "pg": "^8.11.3", - "prom-client": "^15.1.3", - "qrcode": "^1.5.4", - "redis": "^4.6.12", "reflect-metadata": "^0.1.13", - "rxjs": "^7.8.1", - "sharp": "^0.33.1", - "speakeasy": "^2.0.0", - "typeorm": "^0.3.28", - "uuid": "^9.0.1", - "web3": "^4.3.0", - "winston": "^3.11.0", - "winston-daily-rotate-file": "^4.7.1", - "xss": "^1.0.15" + "rxjs": "^7.8.1" }, "devDependencies": { - "@commitlint/cli": "^18.4.3", - "@commitlint/config-conventional": "^18.4.3", "@nestjs/cli": "^10.3.0", "@nestjs/schematics": "^10.0.3", "@nestjs/testing": "^10.3.0", "@types/bcrypt": "^5.0.2", - "@types/compression": "^1.7.5", - "@types/cors": "^2.8.17", - "@types/crypto-js": "^4.2.1", "@types/express": "^4.17.21", - "@types/file-type": "^10.6.0", "@types/jest": "^29.5.14", - "@types/jsonwebtoken": "^9.0.5", - "@types/lodash": "^4.14.202", - "@types/multer": "^1.4.13", "@types/node": "^20.10.4", "@types/passport-jwt": "^3.0.13", - "@types/passport-local": "^1.0.38", - "@types/supertest": "^2.0.16", - "@types/uuid": "^9.0.7", "@typescript-eslint/eslint-plugin": "^6.13.1", "@typescript-eslint/parser": "^6.13.1", - "cross-env": "^10.1.0", "eslint": "^8.54.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-prettier": "^5.0.1", - "husky": "^8.0.3", "jest": "^29.7.0", - "jest-junit": "^16.0.0", - "lint-staged": "^15.2.0", "prettier": "^3.1.0", "prisma": "^6.19.2", "rimraf": "^5.0.5", "source-map-support": "^0.5.21", - "supertest": "^6.3.3", - "testcontainers": "^10.4.0", "ts-jest": "^29.4.6", "ts-loader": "^9.5.1", "ts-node": "^10.9.1", "tsconfig-paths": "^4.2.0", - "typedoc": "^0.28.18", - "typedoc-plugin-markdown": "^4.11.0", "typescript": "^5.3.2" }, "engines": { @@ -129,12 +55,6 @@ "npm": ">=8.0.0" } }, - "node_modules/@adraffy/ens-normalize": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", - "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", - "license": "MIT" - }, "node_modules/@angular-devkit/core": { "version": "17.3.11", "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.11.tgz", @@ -836,13 +756,6 @@ "node": ">=6.9.0" } }, - "node_modules/@balena/dockerignore": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@balena/dockerignore/-/dockerignore-1.0.2.tgz", - "integrity": "sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", @@ -860,25 +773,6 @@ "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/@cacheable/utils": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.3.4.tgz", - "integrity": "sha512-knwKUJEYgIfwShABS1BX6JyJJTglAFcEU7EXqzTdiGCXur4voqkiJkdgZIQtWNFhynzDWERcTYv/sETMu3uJWA==", - "license": "MIT", - "dependencies": { - "hashery": "^1.3.0", - "keyv": "^5.6.0" - } - }, - "node_modules/@cacheable/utils/node_modules/keyv": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", - "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", - "license": "MIT", - "dependencies": { - "@keyv/serialize": "^1.1.1" - } - }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -890,266 +784,6 @@ "node": ">=0.1.90" } }, - "node_modules/@commitlint/cli": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-18.6.1.tgz", - "integrity": "sha512-5IDE0a+lWGdkOvKH892HHAZgbAjcj1mT5QrfA/SVbLJV/BbBMGyKN0W5mhgjekPJJwEQdVNvhl9PwUacY58Usw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/format": "^18.6.1", - "@commitlint/lint": "^18.6.1", - "@commitlint/load": "^18.6.1", - "@commitlint/read": "^18.6.1", - "@commitlint/types": "^18.6.1", - "execa": "^5.0.0", - "lodash.isfunction": "^3.0.9", - "resolve-from": "5.0.0", - "resolve-global": "1.0.0", - "yargs": "^17.0.0" - }, - "bin": { - "commitlint": "cli.js" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/config-conventional": { - "version": "18.6.3", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-18.6.3.tgz", - "integrity": "sha512-8ZrRHqF6je+TRaFoJVwszwnOXb/VeYrPmTwPhf0WxpzpGTcYy1p0SPyZ2eRn/sRi/obnWAcobtDAq6+gJQQNhQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/types": "^18.6.1", - "conventional-changelog-conventionalcommits": "^7.0.2" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/config-validator": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-18.6.1.tgz", - "integrity": "sha512-05uiToBVfPhepcQWE1ZQBR/Io3+tb3gEotZjnI4tTzzPk16NffN6YABgwFQCLmzZefbDcmwWqJWc2XT47q7Znw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/types": "^18.6.1", - "ajv": "^8.11.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/ensure": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-18.6.1.tgz", - "integrity": "sha512-BPm6+SspyxQ7ZTsZwXc7TRQL5kh5YWt3euKmEIBZnocMFkJevqs3fbLRb8+8I/cfbVcAo4mxRlpTPfz8zX7SnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/types": "^18.6.1", - "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": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-18.6.1.tgz", - "integrity": "sha512-7s37a+iWyJiGUeMFF6qBlyZciUkF8odSAnHijbD36YDctLhGKoYltdvuJ/AFfRm6cBLRtRk9cCVPdsEFtt/2rg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/format": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-18.6.1.tgz", - "integrity": "sha512-K8mNcfU/JEFCharj2xVjxGSF+My+FbUHoqR+4GqPGrHNqXOGNio47ziiR4HQUPKtiNs05o8/WyLBoIpMVOP7wg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/types": "^18.6.1", - "chalk": "^4.1.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/is-ignored": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-18.6.1.tgz", - "integrity": "sha512-MOfJjkEJj/wOaPBw5jFjTtfnx72RGwqYIROABudOtJKW7isVjFe9j0t8xhceA02QebtYf4P/zea4HIwnXg8rvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/types": "^18.6.1", - "semver": "7.6.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/lint": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-18.6.1.tgz", - "integrity": "sha512-8WwIFo3jAuU+h1PkYe5SfnIOzp+TtBHpFr4S8oJWhu44IWKuVx6GOPux3+9H1iHOan/rGBaiacicZkMZuluhfQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/is-ignored": "^18.6.1", - "@commitlint/parse": "^18.6.1", - "@commitlint/rules": "^18.6.1", - "@commitlint/types": "^18.6.1" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/load": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-18.6.1.tgz", - "integrity": "sha512-p26x8734tSXUHoAw0ERIiHyW4RaI4Bj99D8YgUlVV9SedLf8hlWAfyIFhHRIhfPngLlCe0QYOdRKYFt8gy56TA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/config-validator": "^18.6.1", - "@commitlint/execute-rule": "^18.6.1", - "@commitlint/resolve-extends": "^18.6.1", - "@commitlint/types": "^18.6.1", - "chalk": "^4.1.0", - "cosmiconfig": "^8.3.6", - "cosmiconfig-typescript-loader": "^5.0.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2", - "lodash.uniq": "^4.5.0", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/message": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-18.6.1.tgz", - "integrity": "sha512-VKC10UTMLcpVjMIaHHsY1KwhuTQtdIKPkIdVEwWV+YuzKkzhlI3aNy6oo1eAN6b/D2LTtZkJe2enHmX0corYRw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/parse": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-18.6.1.tgz", - "integrity": "sha512-eS/3GREtvVJqGZrwAGRwR9Gdno3YcZ6Xvuaa+vUF8j++wsmxrA2En3n0ccfVO2qVOLJC41ni7jSZhQiJpMPGOQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/types": "^18.6.1", - "conventional-changelog-angular": "^7.0.0", - "conventional-commits-parser": "^5.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/read": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-18.6.1.tgz", - "integrity": "sha512-ia6ODaQFzXrVul07ffSgbZGFajpe8xhnDeLIprLeyfz3ivQU1dIoHp7yz0QIorZ6yuf4nlzg4ZUkluDrGN/J/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/top-level": "^18.6.1", - "@commitlint/types": "^18.6.1", - "git-raw-commits": "^2.0.11", - "minimist": "^1.2.6" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/resolve-extends": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-18.6.1.tgz", - "integrity": "sha512-ifRAQtHwK+Gj3Bxj/5chhc4L2LIc3s30lpsyW67yyjsETR6ctHAHRu1FSpt0KqahK5xESqoJ92v6XxoDRtjwEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/config-validator": "^18.6.1", - "@commitlint/types": "^18.6.1", - "import-fresh": "^3.0.0", - "lodash.mergewith": "^4.6.2", - "resolve-from": "^5.0.0", - "resolve-global": "^1.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/rules": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-18.6.1.tgz", - "integrity": "sha512-kguM6HxZDtz60v/zQYOe0voAtTdGybWXefA1iidjWYmyUUspO1zBPQEmJZ05/plIAqCVyNUTAiRPWIBKLCrGew==", - "dev": true, - "license": "MIT", - "dependencies": { - "@commitlint/ensure": "^18.6.1", - "@commitlint/message": "^18.6.1", - "@commitlint/to-lines": "^18.6.1", - "@commitlint/types": "^18.6.1", - "execa": "^5.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/to-lines": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-18.6.1.tgz", - "integrity": "sha512-Gl+orGBxYSNphx1+83GYeNy5N0dQsHBQ9PJMriaLQDB51UQHCVLBT/HBdOx5VaYksivSf5Os55TLePbRLlW50Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/top-level": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-18.6.1.tgz", - "integrity": "sha512-HyiHQZUTf0+r0goTCDs/bbVv/LiiQ7AVtz6KIar+8ZrseB9+YJAIo8HQ2IC2QT1y3N1lbW6OqVEsTHjbT6hGSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^5.0.0" - }, - "engines": { - "node": ">=v18" - } - }, - "node_modules/@commitlint/types": { - "version": "18.6.1", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-18.6.1.tgz", - "integrity": "sha512-gwRLBLra/Dozj2OywopeuHj2ac26gjGkz2cZ+86cTJOdtWfiRRr4+e77ZDAGc6MDWxaWheI+mAV5TLWWRwqrFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0" - }, - "engines": { - "node": ">=v18" - } - }, "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", @@ -1174,34 +808,6 @@ "@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/@emnapi/runtime": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", - "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@epic-web/invariant": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz", - "integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==", - "dev": true, - "license": "MIT" - }, "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", @@ -1313,564 +919,492 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@ethereumjs/rlp": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-5.0.2.tgz", - "integrity": "sha512-DziebCdg4JpGlEqEdGgXmjqcFoJi+JGulUXwEjsZGAscAQ7MyD/7LE/GVCP29vEQxKc7AAwjT3A2ywHp2xfoCA==", - "license": "MPL-2.0", - "bin": { - "rlp": "bin/rlp.cjs" + "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": ">=18" + "node": ">=10.10.0" } }, - "node_modules/@ethereumjs/util": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-9.1.0.tgz", - "integrity": "sha512-XBEKsYqLGXLah9PNJbgdkigthkG7TAGvlD/sH12beMXEyHDyigfcbdvHhmLyDWgDyOJn4QwiQUaF7yeuhnjdog==", - "license": "MPL-2.0", + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", "dependencies": { - "@ethereumjs/rlp": "^5.0.2", - "ethereum-cryptography": "^2.2.1" - }, - "engines": { - "node": ">=18" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@ethereumjs/util/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", - "license": "MIT", + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", "dependencies": { - "@noble/hashes": "1.4.0" + "brace-expansion": "^1.1.7" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": "*" } }, - "node_modules/@ethereumjs/util/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "license": "MIT", + "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": ">= 16" + "node": ">=12.22" }, "funding": { - "url": "https://paulmillr.com/funding/" + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@ethereumjs/util/node_modules/ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", - "license": "MIT", - "dependencies": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" - } + "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/@ethersproject/abi": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.8.0.tgz", - "integrity": "sha512-b9YS/43ObplgyV6SlyQsG53/vkSal0MNA1fskSC4mbnCMi8R+NkcH8K9FPYNESf6jUefBUniE4SOKms0E/KK1Q==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "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==", + "dev": true, + "license": "ISC", "dependencies": { - "@ethersproject/address": "^5.8.0", - "@ethersproject/bignumber": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/constants": "^5.8.0", - "@ethersproject/hash": "^5.8.0", - "@ethersproject/keccak256": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "@ethersproject/strings": "^5.8.0" + "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/@ethersproject/abstract-provider": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.8.0.tgz", - "integrity": "sha512-wC9SFcmh4UK0oKuLJQItoQdzS/qZ51EJegK6EmAWlh+OptpQ/npECOR3QqECd8iGHC0RJb4WKbVdSfif4ammrg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], + "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==", + "dev": true, "license": "MIT", - "dependencies": { - "@ethersproject/bignumber": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/networks": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "@ethersproject/transactions": "^5.8.0", - "@ethersproject/web": "^5.8.0" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@ethersproject/abstract-signer": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.8.0.tgz", - "integrity": "sha512-N0XhZTswXcmIZQdYtUnd79VJzvEwXQw6PK0dTl9VoYrEBxxCPXqS0Eod7q5TNKRxe1/5WUMuR0u0nqTF/avdCA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], + "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==", + "dev": true, "license": "MIT", - "dependencies": { - "@ethersproject/abstract-provider": "^5.8.0", - "@ethersproject/bignumber": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/properties": "^5.8.0" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@ethersproject/address": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.8.0.tgz", - "integrity": "sha512-GhH/abcC46LJwshoN+uBNoKVFPxUuZm6dA257z0vZkKmU1+t8xTn8oK7B9qrj8W2rFRMch4gbJl6PmVxjxBEBA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bignumber": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/keccak256": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/rlp": "^5.8.0" - } + "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==", + "dev": true, + "license": "MIT" }, - "node_modules/@ethersproject/base64": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.8.0.tgz", - "integrity": "sha512-lN0oIwfkYj9LbPx4xEkie6rAMJtySbpOAFXSDVQaBnAzYfB4X2Qr+FXJGxMoc3Bxp2Sm8OwvzMrywxyw0gLjIQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], + "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==", + "dev": true, "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.8.0" + "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/@ethersproject/bignumber": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.8.0.tgz", - "integrity": "sha512-ZyaT24bHaSeJon2tGPKIiHszWjD/54Sz8t57Toch475lCLljC6MgPmxk7Gtzz+ddNN5LuHea9qhAe0x3D+uYPA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "bn.js": "^5.2.1" + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@ethersproject/bytes": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.8.0.tgz", - "integrity": "sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], + "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==", + "dev": true, "license": "MIT", "dependencies": { - "@ethersproject/logger": "^5.8.0" + "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/@ethersproject/constants": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.8.0.tgz", - "integrity": "sha512-wigX4lrf5Vu+axVTIvNsuL6YrV4O5AXl5ubcURKMEME5TnWBouUh0CDTWxZ2GpnRn1kcCgE7l8O5+VbV9QTTcg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "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": { - "@ethersproject/bignumber": "^5.8.0" + "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/@ethersproject/hash": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.8.0.tgz", - "integrity": "sha512-ac/lBcTbEWW/VGJij0CNSw/wPcw9bSRgCB0AIBz8CvED/jfvDoV9hsIIiWfvWmFEi8RcXtlNwp2jv6ozWOsooA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], + "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": { - "@ethersproject/abstract-signer": "^5.8.0", - "@ethersproject/address": "^5.8.0", - "@ethersproject/base64": "^5.8.0", - "@ethersproject/bignumber": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/keccak256": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "@ethersproject/strings": "^5.8.0" + "sprintf-js": "~1.0.2" } }, - "node_modules/@ethersproject/keccak256": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.8.0.tgz", - "integrity": "sha512-A1pkKLZSz8pDaQ1ftutZoaN46I6+jvuqugx5KYNeQOPqq+JZ0Txm7dlWesCHB5cndJSu5vP2VKptKf7cksERng==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], + "node_modules/@istanbuljs/load-nyc-config/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", - "dependencies": { - "@ethersproject/bytes": "^5.8.0", - "js-sha3": "0.8.0" + "engines": { + "node": ">=6" } }, - "node_modules/@ethersproject/logger": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.8.0.tgz", - "integrity": "sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT" - }, - "node_modules/@ethersproject/networks": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.8.0.tgz", - "integrity": "sha512-egPJh3aPVAzbHwq8DD7Po53J4OUSsA1MjQp8Vf/OZPav5rlmWUaFLiq8cvQiGK0Z5K6LYzm29+VA/p4RL1FzNg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], + "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": { - "@ethersproject/logger": "^5.8.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@ethersproject/properties": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.8.0.tgz", - "integrity": "sha512-PYuiEoQ+FMaZZNGrStmN7+lWjlsoufGIHdww7454FIaGdbe/p5rnaCXTr5MtBYl3NkeoVhHZuyzChPeGeKIpQw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], + "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": { - "@ethersproject/logger": "^5.8.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@ethersproject/rlp": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.8.0.tgz", - "integrity": "sha512-LqZgAznqDbiEunaUvykH2JAoXTT9NV0Atqk8rQN9nx9SEgThA/WMx5DnW8a9FOufo//6FZOCHZ+XiClzgbqV9Q==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], + "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": { - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/logger": "^5.8.0" + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@ethersproject/signing-key": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.8.0.tgz", - "integrity": "sha512-LrPW2ZxoigFi6U6aVkFN/fa9Yx/+4AtIUe4/HACTvKJdhm0eeb107EVCIQcrLZkxaSIgc/eCrX8Q1GtbH+9n3w==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], + "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": { - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "bn.js": "^5.2.1", - "elliptic": "6.6.1", - "hash.js": "1.1.7" + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@ethersproject/strings": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.8.0.tgz", - "integrity": "sha512-qWEAk0MAvl0LszjdfnZ2uC8xbR2wdv4cDabyHiBh3Cldq/T8dPH3V4BbBsAYJUeonwD+8afVXld274Ls+Y1xXg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], + "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": { - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/constants": "^5.8.0", - "@ethersproject/logger": "^5.8.0" + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@ethersproject/transactions": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.8.0.tgz", - "integrity": "sha512-UglxSDjByHG0TuU17bDfCemZ3AnKO2vYrL5/2n2oXvKzvb7Cz+W9gOWXKARjp2URVwcWlQlPOEQyAviKwT4AHg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], + "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": { - "@ethersproject/address": "^5.8.0", - "@ethersproject/bignumber": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/constants": "^5.8.0", - "@ethersproject/keccak256": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "@ethersproject/rlp": "^5.8.0", - "@ethersproject/signing-key": "^5.8.0" + "@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/@ethersproject/web": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.8.0.tgz", - "integrity": "sha512-j7+Ksi/9KfGviws6Qtf9Q7KCqRhpwrYKQPs+JBA/rKVFF/yaWLHJEH3zfVP2plVu+eys0d2DlFmhoQJayFewcw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], + "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": { - "@ethersproject/base64": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "@ethersproject/strings": "^5.8.0" + "@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/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "node_modules/@jest/core/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": ">=14" + "node": ">=8" } }, - "node_modules/@gerrit0/mini-shiki": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.23.0.tgz", - "integrity": "sha512-bEMORlG0cqdjVyCEuU0cDQbORWX+kYCeo0kV1lbxF5bt4r7SID2l9bqsxJEM0zndaxpOUT7riCyIVEuqq/Ynxg==", + "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": { - "@shikijs/engine-oniguruma": "^3.23.0", - "@shikijs/langs": "^3.23.0", - "@shikijs/themes": "^3.23.0", - "@shikijs/types": "^3.23.0", - "@shikijs/vscode-textmate": "^10.0.2" + "@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/@grpc/grpc-js": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.3.tgz", - "integrity": "sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA==", - "license": "Apache-2.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": { - "@grpc/proto-loader": "^0.8.0", - "@js-sdsl/ordered-map": "^4.4.2" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, "engines": { - "node": ">=12.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@grpc/grpc-js/node_modules/@grpc/proto-loader": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.0.tgz", - "integrity": "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==", - "license": "Apache-2.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": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.5.3", - "yargs": "^17.7.2" - }, - "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + "jest-get-type": "^29.6.3" }, "engines": { - "node": ">=6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@grpc/proto-loader": { - "version": "0.7.15", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz", - "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==", + "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": "Apache-2.0", + "license": "MIT", "dependencies": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.2.5", - "yargs": "^17.7.2" - }, - "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + "@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": ">=6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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", + "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": { - "@hapi/hoek": "^9.0.0" + "@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/@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", + "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": "Apache-2.0", + "license": "MIT", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@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": ">=10.10.0" + "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/@humanwhocodes/config-array/node_modules/brace-expansion": { + "node_modules/@jest/reporters/node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", @@ -1881,7 +1415,29 @@ "concat-map": "0.0.1" } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "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/@jest/reporters/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", @@ -1894,11604 +1450,1765 @@ "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==", + "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": "Apache-2.0", - "engines": { - "node": ">=12.22" + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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/@img/sharp-darwin-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", - "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", - "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", - "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", - "cpu": [ - "arm" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", - "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", - "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", - "cpu": [ - "s390x" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", - "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", - "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", - "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", - "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", - "cpu": [ - "arm" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.0.5" - } - }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", - "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", - "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", - "cpu": [ - "s390x" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.0.4" - } - }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", - "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", - "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", - "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-wasm32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", - "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", - "cpu": [ - "wasm32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.2.0" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", - "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", - "cpu": [ - "ia32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", - "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@ioredis/commands": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.5.0.tgz", - "integrity": "sha512-eUgLqrMf8nJkZxT24JvVRrQya1vZkQh8BBeYNwGDqa5I0VUi8ACx7uFvAaLxintokpTenkK6DASvo/bvNbBGow==", - "license": "MIT" - }, - "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.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "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/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/@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/core/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/@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/reporters/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@jest/reporters/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "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/@jest/reporters/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "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==", - "dev": 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/@js-sdsl/ordered-map": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", - "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/@keyv/serialize": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz", - "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==", - "license": "MIT" - }, - "node_modules/@liaoliaots/nestjs-redis": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@liaoliaots/nestjs-redis/-/nestjs-redis-10.0.0.tgz", - "integrity": "sha512-uCTmlzM4q+UYADwsJEQph0mbf4u0MrktFhByi50M5fNy/+fJoWlhSqrgvjtVKjHnqydxy1gyuU6vHJEOBp9cjg==", - "license": "MIT", - "dependencies": { - "tslib": "2.7.0" - }, - "engines": { - "node": ">=16.13.0" - }, - "peerDependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/core": "^10.0.0", - "ioredis": "^5.0.0" - } - }, - "node_modules/@liaoliaots/nestjs-redis/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", - "license": "0BSD" - }, - "node_modules/@ljharb/through": { - "version": "2.3.14", - "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.14.tgz", - "integrity": "sha512-ajBvlKpWucBB17FuQYUShqpqy8GRgYEpJW0vWJbUu1CV9lWyrDCapy0lScU8T8Z6qn49sSwJB3+M+evYIdGg+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/@lukeed/csprng": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", - "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@microsoft/tsdoc": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.1.tgz", - "integrity": "sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==", - "license": "MIT" - }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", - "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", - "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", - "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", - "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", - "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", - "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@nestjs/bull": { - "version": "10.2.3", - "resolved": "https://registry.npmjs.org/@nestjs/bull/-/bull-10.2.3.tgz", - "integrity": "sha512-Gy90JjFCfYhWFBeoBSidc7rEEf2BNhkJ3RfK8ym589POOldwAra2xcnFBi0ZuhhOV60GcrCJBBkdrUbAMM670w==", - "license": "MIT", - "dependencies": { - "@nestjs/bull-shared": "^10.2.3", - "tslib": "2.8.1" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0", - "bull": "^3.3 || ^4.0.0" - } - }, - "node_modules/@nestjs/bull-shared": { - "version": "10.2.3", - "resolved": "https://registry.npmjs.org/@nestjs/bull-shared/-/bull-shared-10.2.3.tgz", - "integrity": "sha512-XcgAjNOgq6b5DVCytxhR5BKiwWo7hsusVeyE7sfFnlXRHeEtIuC2hYWBr/ZAtvL/RH0/O0tqtq0rVl972nbhJw==", - "license": "MIT", - "dependencies": { - "tslib": "2.8.1" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0" - } - }, - "node_modules/@nestjs/cache-manager": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@nestjs/cache-manager/-/cache-manager-3.1.0.tgz", - "integrity": "sha512-pEIqYZrBcE8UdkJmZRduurvoUfdU+3kRPeO1R2muiMbZnRuqlki5klFFNllO9LyYWzrx98bd1j0PSPKSJk1Wbw==", - "license": "MIT", - "peerDependencies": { - "@nestjs/common": "^9.0.0 || ^10.0.0 || ^11.0.0", - "@nestjs/core": "^9.0.0 || ^10.0.0 || ^11.0.0", - "cache-manager": ">=6", - "keyv": ">=5", - "rxjs": "^7.8.1" - } - }, - "node_modules/@nestjs/cli": { - "version": "10.4.9", - "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.4.9.tgz", - "integrity": "sha512-s8qYd97bggqeK7Op3iD49X2MpFtW4LVNLAwXFkfbRxKME6IYT7X0muNTJ2+QfI8hpbNx9isWkrLWIp+g5FOhiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-devkit/core": "17.3.11", - "@angular-devkit/schematics": "17.3.11", - "@angular-devkit/schematics-cli": "17.3.11", - "@nestjs/schematics": "^10.0.1", - "chalk": "4.1.2", - "chokidar": "3.6.0", - "cli-table3": "0.6.5", - "commander": "4.1.1", - "fork-ts-checker-webpack-plugin": "9.0.2", - "glob": "10.4.5", - "inquirer": "8.2.6", - "node-emoji": "1.11.0", - "ora": "5.4.1", - "tree-kill": "1.2.2", - "tsconfig-paths": "4.2.0", - "tsconfig-paths-webpack-plugin": "4.2.0", - "typescript": "5.7.2", - "webpack": "5.97.1", - "webpack-node-externals": "3.0.0" - }, - "bin": { - "nest": "bin/nest.js" - }, - "engines": { - "node": ">= 16.14" - }, - "peerDependencies": { - "@swc/cli": "^0.1.62 || ^0.3.0 || ^0.4.0 || ^0.5.0", - "@swc/core": "^1.3.62" - }, - "peerDependenciesMeta": { - "@swc/cli": { - "optional": true - }, - "@swc/core": { - "optional": true - } - } - }, - "node_modules/@nestjs/cli/node_modules/typescript": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", - "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/@nestjs/common": { - "version": "10.4.22", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.22.tgz", - "integrity": "sha512-fxJ4v85nDHaqT1PmfNCQ37b/jcv2OojtXTaK1P2uAXhzLf9qq6WNUOFvxBrV4fhQek1EQoT1o9oj5xAZmv3NRw==", - "license": "MIT", - "dependencies": { - "file-type": "20.4.1", - "iterare": "1.2.1", - "tslib": "2.8.1", - "uid": "2.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "class-transformer": "*", - "class-validator": "*", - "reflect-metadata": "^0.1.12 || ^0.2.0", - "rxjs": "^7.1.0" - }, - "peerDependenciesMeta": { - "class-transformer": { - "optional": true - }, - "class-validator": { - "optional": true - } - } - }, - "node_modules/@nestjs/config": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-3.3.0.tgz", - "integrity": "sha512-pdGTp8m9d0ZCrjTpjkUbZx6gyf2IKf+7zlkrPNMsJzYZ4bFRRTpXrnj+556/5uiI6AfL5mMrJc2u7dB6bvM+VA==", - "license": "MIT", - "dependencies": { - "dotenv": "16.4.5", - "dotenv-expand": "10.0.0", - "lodash": "4.17.21" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "rxjs": "^7.1.0" - } - }, - "node_modules/@nestjs/config/node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/@nestjs/core": { - "version": "10.4.22", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.22.tgz", - "integrity": "sha512-6IX9+VwjiKtCjx+mXVPncpkQ5ZjKfmssOZPFexmT+6T9H9wZ3svpYACAo7+9e7Nr9DZSoRZw3pffkJP7Z0UjaA==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@nuxtjs/opencollective": "0.3.2", - "fast-safe-stringify": "2.1.1", - "iterare": "1.2.1", - "path-to-regexp": "3.3.0", - "tslib": "2.8.1", - "uid": "2.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/microservices": "^10.0.0", - "@nestjs/platform-express": "^10.0.0", - "@nestjs/websockets": "^10.0.0", - "reflect-metadata": "^0.1.12 || ^0.2.0", - "rxjs": "^7.1.0" - }, - "peerDependenciesMeta": { - "@nestjs/microservices": { - "optional": true - }, - "@nestjs/platform-express": { - "optional": true - }, - "@nestjs/websockets": { - "optional": true - } - } - }, - "node_modules/@nestjs/jwt": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-11.0.2.tgz", - "integrity": "sha512-rK8aE/3/Ma45gAWfCksAXUNbOoSOUudU0Kn3rT39htPF7wsYXtKfjALKeKKJbFrIWbLjsbqfXX5bIJNvgBugGA==", - "license": "MIT", - "dependencies": { - "@types/jsonwebtoken": "9.0.10", - "jsonwebtoken": "9.0.3" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" - } - }, - "node_modules/@nestjs/mapped-types": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.5.tgz", - "integrity": "sha512-bSJv4pd6EY99NX9CjBIyn4TVDoSit82DUZlL4I3bqNfy5Gt+gXTa86i3I/i0iIV9P4hntcGM5GyO+FhZAhxtyg==", - "license": "MIT", - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "class-transformer": "^0.4.0 || ^0.5.0", - "class-validator": "^0.13.0 || ^0.14.0", - "reflect-metadata": "^0.1.12 || ^0.2.0" - }, - "peerDependenciesMeta": { - "class-transformer": { - "optional": true - }, - "class-validator": { - "optional": true - } - } - }, - "node_modules/@nestjs/passport": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-10.0.3.tgz", - "integrity": "sha512-znJ9Y4S8ZDVY+j4doWAJ8EuuVO7SkQN3yOBmzxbGaXbvcSwFDAdGJ+OMCg52NdzIO4tQoN4pYKx8W6M0ArfFRQ==", - "license": "MIT", - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "passport": "^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0" - } - }, - "node_modules/@nestjs/platform-express": { - "version": "10.4.22", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.22.tgz", - "integrity": "sha512-ySSq7Py/DFozzZdNDH67m/vHoeVdphDniWBnl6q5QVoXldDdrZIHLXLRMPayTDh5A95nt7jjJzmD4qpTbNQ6tA==", - "license": "MIT", - "dependencies": { - "body-parser": "1.20.4", - "cors": "2.8.5", - "express": "4.22.1", - "multer": "2.0.2", - "tslib": "2.8.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/core": "^10.0.0" - } - }, - "node_modules/@nestjs/platform-express/node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@nestjs/platform-express/node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@nestjs/platform-express/node_modules/cookie-signature": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "license": "MIT" - }, - "node_modules/@nestjs/platform-express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/@nestjs/platform-express/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/@nestjs/platform-express/node_modules/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "~1.20.3", - "content-disposition": "~0.5.4", - "content-type": "~1.0.4", - "cookie": "~0.7.1", - "cookie-signature": "~1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.3.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "~0.1.12", - "proxy-addr": "~2.0.7", - "qs": "~6.14.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "~0.19.0", - "serve-static": "~1.16.2", - "setprototypeof": "1.2.0", - "statuses": "~2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@nestjs/platform-express/node_modules/finalhandler": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", - "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "statuses": "~2.0.2", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@nestjs/platform-express/node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@nestjs/platform-express/node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@nestjs/platform-express/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@nestjs/platform-express/node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@nestjs/platform-express/node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "license": "MIT" - }, - "node_modules/@nestjs/platform-express/node_modules/send": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", - "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.4.1", - "range-parser": "~1.2.1", - "statuses": "~2.0.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/@nestjs/platform-express/node_modules/serve-static": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", - "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "~0.19.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/@nestjs/schedule": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@nestjs/schedule/-/schedule-4.1.2.tgz", - "integrity": "sha512-hCTQ1lNjIA5EHxeu8VvQu2Ed2DBLS1GSC6uKPYlBiQe6LL9a7zfE9iVSK+zuK8E2odsApteEBmfAQchc8Hx0Gg==", - "license": "MIT", - "dependencies": { - "cron": "3.2.1", - "uuid": "11.0.3" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0" - } - }, - "node_modules/@nestjs/schedule/node_modules/uuid": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", - "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/esm/bin/uuid" - } - }, - "node_modules/@nestjs/schematics": { - "version": "10.2.3", - "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-10.2.3.tgz", - "integrity": "sha512-4e8gxaCk7DhBxVUly2PjYL4xC2ifDFexCqq1/u4TtivLGXotVk0wHdYuPYe1tHTHuR1lsOkRbfOCpkdTnigLVg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-devkit/core": "17.3.11", - "@angular-devkit/schematics": "17.3.11", - "comment-json": "4.2.5", - "jsonc-parser": "3.3.1", - "pluralize": "8.0.0" - }, - "peerDependencies": { - "typescript": ">=4.8.2" - } - }, - "node_modules/@nestjs/schematics/node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@nestjs/swagger": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-7.4.2.tgz", - "integrity": "sha512-Mu6TEn1M/owIvAx2B4DUQObQXqo2028R2s9rSZ/hJEgBK95+doTwS0DjmVA2wTeZTyVtXOoN7CsoM5pONBzvKQ==", - "license": "MIT", - "dependencies": { - "@microsoft/tsdoc": "^0.15.0", - "@nestjs/mapped-types": "2.0.5", - "js-yaml": "4.1.0", - "lodash": "4.17.21", - "path-to-regexp": "3.3.0", - "swagger-ui-dist": "5.17.14" - }, - "peerDependencies": { - "@fastify/static": "^6.0.0 || ^7.0.0", - "@nestjs/common": "^9.0.0 || ^10.0.0", - "@nestjs/core": "^9.0.0 || ^10.0.0", - "class-transformer": "*", - "class-validator": "*", - "reflect-metadata": "^0.1.12 || ^0.2.0" - }, - "peerDependenciesMeta": { - "@fastify/static": { - "optional": true - }, - "class-transformer": { - "optional": true - }, - "class-validator": { - "optional": true - } - } - }, - "node_modules/@nestjs/terminus": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@nestjs/terminus/-/terminus-10.3.0.tgz", - "integrity": "sha512-vOJGCwt1OgrFuuxWQwPoaHqy9m9CfIk2qMUX2mosZLK5dFVJSEjHXrklkh3/Fw9PiUnfzvYFfiAdJRzUaxx+5Q==", - "license": "MIT", - "dependencies": { - "boxen": "5.1.2", - "check-disk-space": "3.4.0" - }, - "peerDependencies": { - "@grpc/grpc-js": "*", - "@grpc/proto-loader": "*", - "@mikro-orm/core": "*", - "@mikro-orm/nestjs": "*", - "@nestjs/axios": "^1.0.0 || ^2.0.0 || ^3.0.0", - "@nestjs/common": "^9.0.0 || ^10.0.0", - "@nestjs/core": "^9.0.0 || ^10.0.0", - "@nestjs/microservices": "^9.0.0 || ^10.0.0", - "@nestjs/mongoose": "^9.0.0 || ^10.0.0", - "@nestjs/sequelize": "^9.0.0 || ^10.0.0", - "@nestjs/typeorm": "^9.0.0 || ^10.0.0", - "@prisma/client": "*", - "mongoose": "*", - "reflect-metadata": "0.1.x || 0.2.x", - "rxjs": "7.x", - "sequelize": "*", - "typeorm": "*" - }, - "peerDependenciesMeta": { - "@grpc/grpc-js": { - "optional": true - }, - "@grpc/proto-loader": { - "optional": true - }, - "@mikro-orm/core": { - "optional": true - }, - "@mikro-orm/nestjs": { - "optional": true - }, - "@nestjs/axios": { - "optional": true - }, - "@nestjs/microservices": { - "optional": true - }, - "@nestjs/mongoose": { - "optional": true - }, - "@nestjs/sequelize": { - "optional": true - }, - "@nestjs/typeorm": { - "optional": true - }, - "@prisma/client": { - "optional": true - }, - "mongoose": { - "optional": true - }, - "sequelize": { - "optional": true - }, - "typeorm": { - "optional": true - } - } - }, - "node_modules/@nestjs/testing": { - "version": "10.4.22", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.22.tgz", - "integrity": "sha512-HO9aPus3bAedAC+jKVAA8jTdaj4fs5M9fing4giHrcYV2txe9CvC1l1WAjwQ9RDhEHdugjY4y+FZA/U/YqPZrA==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "2.8.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/core": "^10.0.0", - "@nestjs/microservices": "^10.0.0", - "@nestjs/platform-express": "^10.0.0" - }, - "peerDependenciesMeta": { - "@nestjs/microservices": { - "optional": true - }, - "@nestjs/platform-express": { - "optional": true - } - } - }, - "node_modules/@nestjs/throttler": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@nestjs/throttler/-/throttler-5.2.0.tgz", - "integrity": "sha512-G/G/MV3xf6sy1DwmnJsgeL+d2tQ/xGRNa9ZhZjm9Kyxp+3+ylGzwJtcnhWlN82PMEp3TiDQpTt+9waOIg/bpPg==", - "license": "MIT", - "peerDependencies": { - "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", - "@nestjs/core": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", - "reflect-metadata": "^0.1.13 || ^0.2.0" - } - }, - "node_modules/@nestjs/typeorm": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@nestjs/typeorm/-/typeorm-10.0.2.tgz", - "integrity": "sha512-H738bJyydK4SQkRCTeh1aFBxoO1E9xdL/HaLGThwrqN95os5mEyAtK7BLADOS+vldP4jDZ2VQPLj4epWwRqCeQ==", - "license": "MIT", - "dependencies": { - "uuid": "9.0.1" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0", - "reflect-metadata": "^0.1.13 || ^0.2.0", - "rxjs": "^7.2.0", - "typeorm": "^0.3.0" - } - }, - "node_modules/@noble/curves": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", - "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.3.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/secp256k1": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", - "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT" - }, - "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/@nomicfoundation/edr": { - "version": "0.12.0-next.23", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.12.0-next.23.tgz", - "integrity": "sha512-F2/6HZh8Q9RsgkOIkRrckldbhPjIZY7d4mT9LYuW68miwGQ5l7CkAgcz9fRRiurA0+YJhtsbx/EyrD9DmX9BOw==", - "license": "MIT", - "dependencies": { - "@nomicfoundation/edr-darwin-arm64": "0.12.0-next.23", - "@nomicfoundation/edr-darwin-x64": "0.12.0-next.23", - "@nomicfoundation/edr-linux-arm64-gnu": "0.12.0-next.23", - "@nomicfoundation/edr-linux-arm64-musl": "0.12.0-next.23", - "@nomicfoundation/edr-linux-x64-gnu": "0.12.0-next.23", - "@nomicfoundation/edr-linux-x64-musl": "0.12.0-next.23", - "@nomicfoundation/edr-win32-x64-msvc": "0.12.0-next.23" - }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/@nomicfoundation/edr-darwin-arm64": { - "version": "0.12.0-next.23", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.12.0-next.23.tgz", - "integrity": "sha512-Amh7mRoDzZyJJ4efqoePqdoZOzharmSOttZuJDlVE5yy07BoE8hL6ZRpa5fNYn0LCqn/KoWs8OHANWxhKDGhvQ==", - "license": "MIT", - "engines": { - "node": ">= 20" - } - }, - "node_modules/@nomicfoundation/edr-darwin-x64": { - "version": "0.12.0-next.23", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.12.0-next.23.tgz", - "integrity": "sha512-9wn489FIQm7m0UCD+HhktjWx6vskZzeZD9oDc2k9ZvbBzdXwPp5tiDqUBJ+eQpByAzCDfteAJwRn2lQCE0U+Iw==", - "license": "MIT", - "engines": { - "node": ">= 20" - } - }, - "node_modules/@nomicfoundation/edr-linux-arm64-gnu": { - "version": "0.12.0-next.23", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.12.0-next.23.tgz", - "integrity": "sha512-nlk5EejSzEUfEngv0Jkhqq3/wINIfF2ED9wAofc22w/V1DV99ASh9l3/e/MIHOQFecIZ9MDqt0Em9/oDyB1Uew==", - "license": "MIT", - "engines": { - "node": ">= 20" - } - }, - "node_modules/@nomicfoundation/edr-linux-arm64-musl": { - "version": "0.12.0-next.23", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.12.0-next.23.tgz", - "integrity": "sha512-SJuPBp3Rc6vM92UtVTUxZQ/QlLhLfwTftt2XUiYohmGKB3RjGzpgduEFMCA0LEnucUckU6UHrJNFHiDm77C4PQ==", - "license": "MIT", - "engines": { - "node": ">= 20" - } - }, - "node_modules/@nomicfoundation/edr-linux-x64-gnu": { - "version": "0.12.0-next.23", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.12.0-next.23.tgz", - "integrity": "sha512-NU+Qs3u7Qt6t3bJFdmmjd5CsvgI2bPPzO31KifM2Ez96/jsXYho5debtTQnimlb5NAqiHTSlxjh/F8ROcptmeQ==", - "license": "MIT", - "engines": { - "node": ">= 20" - } - }, - "node_modules/@nomicfoundation/edr-linux-x64-musl": { - "version": "0.12.0-next.23", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.12.0-next.23.tgz", - "integrity": "sha512-F78fZA2h6/ssiCSZOovlgIu0dUeI7ItKPsDDF3UUlIibef052GCXmliMinC90jVPbrjUADMd1BUwjfI0Z8OllQ==", - "license": "MIT", - "engines": { - "node": ">= 20" - } - }, - "node_modules/@nomicfoundation/edr-win32-x64-msvc": { - "version": "0.12.0-next.23", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.12.0-next.23.tgz", - "integrity": "sha512-IfJZQJn7d/YyqhmguBIGoCKjE9dKjbu6V6iNEPApfwf5JyyjHYyyfkLU4rf7hygj57bfH4sl1jtQ6r8HnT62lw==", - "license": "MIT", - "engines": { - "node": ">= 20" - } - }, - "node_modules/@nomicfoundation/hardhat-toolbox": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-4.0.0.tgz", - "integrity": "sha512-jhcWHp0aHaL0aDYj8IJl80v4SZXWMS1A2XxXa1CA6pBiFfJKuZinCkO6wb+POAt0LIfXB3gA3AgdcOccrcwBwA==", - "license": "MIT", - "peerDependencies": { - "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", - "@nomicfoundation/hardhat-ethers": "^3.0.0", - "@nomicfoundation/hardhat-network-helpers": "^1.0.0", - "@nomicfoundation/hardhat-verify": "^2.0.0", - "@typechain/ethers-v6": "^0.5.0", - "@typechain/hardhat": "^9.0.0", - "@types/chai": "^4.2.0", - "@types/mocha": ">=9.1.0", - "@types/node": ">=16.0.0", - "chai": "^4.2.0", - "ethers": "^6.4.0", - "hardhat": "^2.11.0", - "hardhat-gas-reporter": "^1.0.8", - "solidity-coverage": "^0.8.1", - "ts-node": ">=8.0.0", - "typechain": "^8.3.0", - "typescript": ">=4.5.0" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.2.tgz", - "integrity": "sha512-q4n32/FNKIhQ3zQGGw5CvPF6GTvDCpYwIf7bEY/dZTZbgfDsHyjJwURxUJf3VQuuJj+fDIFl4+KkBVbw4Ef6jA==", - "license": "MIT", - "engines": { - "node": ">= 12" - }, - "optionalDependencies": { - "@nomicfoundation/solidity-analyzer-darwin-arm64": "0.1.2", - "@nomicfoundation/solidity-analyzer-darwin-x64": "0.1.2", - "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": "0.1.2", - "@nomicfoundation/solidity-analyzer-linux-arm64-musl": "0.1.2", - "@nomicfoundation/solidity-analyzer-linux-x64-gnu": "0.1.2", - "@nomicfoundation/solidity-analyzer-linux-x64-musl": "0.1.2", - "@nomicfoundation/solidity-analyzer-win32-x64-msvc": "0.1.2" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-darwin-arm64": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.2.tgz", - "integrity": "sha512-JaqcWPDZENCvm++lFFGjrDd8mxtf+CtLd2MiXvMNTBD33dContTZ9TWETwNFwg7JTJT5Q9HEecH7FA+HTSsIUw==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-darwin-x64": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.2.tgz", - "integrity": "sha512-fZNmVztrSXC03e9RONBT+CiksSeYcxI1wlzqyr0L7hsQlK1fzV+f04g2JtQ1c/Fe74ZwdV6aQBdd6Uwl1052sw==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-gnu": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.2.tgz", - "integrity": "sha512-3d54oc+9ZVBuB6nbp8wHylk4xh0N0Gc+bk+/uJae+rUgbOBwQSfuGIbAZt1wBXs5REkSmynEGcqx6DutoK0tPA==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-musl": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.2.tgz", - "integrity": "sha512-iDJfR2qf55vgsg7BtJa7iPiFAsYf2d0Tv/0B+vhtnI16+wfQeTbP7teookbGvAo0eJo7aLLm0xfS/GTkvHIucA==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-gnu": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.2.tgz", - "integrity": "sha512-9dlHMAt5/2cpWyuJ9fQNOUXFB/vgSFORg1jpjX1Mh9hJ/MfZXlDdHQ+DpFCs32Zk5pxRBb07yGvSHk9/fezL+g==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-musl": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.2.tgz", - "integrity": "sha512-GzzVeeJob3lfrSlDKQw2bRJ8rBf6mEYaWY+gW0JnTDHINA0s2gPR4km5RLIj1xeZZOYz4zRw+AEeYgLRqB2NXg==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-win32-x64-msvc": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.2.tgz", - "integrity": "sha512-Fdjli4DCcFHb4Zgsz0uEJXZ2K7VEO+w5KVv7HmT7WO10iODdU9csC2az4jrhEsRtiR9Gfd74FlG0NYlw1BMdyA==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/@nuxtjs/opencollective": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", - "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "consola": "^2.15.0", - "node-fetch": "^2.6.1" - }, - "bin": { - "opencollective": "bin/opencollective.js" - }, - "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" - } - }, - "node_modules/@opentelemetry/api": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", - "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", - "license": "Apache-2.0", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@opentelemetry/api-logs": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.212.0.tgz", - "integrity": "sha512-TEEVrLbNROUkYY51sBJGk7lO/OLjuepch8+hmpM6ffMJQ2z/KVCjdHuCFX6fJj8OkJP2zckPjrJzQtXU3IAsFg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api": "^1.3.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@opentelemetry/auto-instrumentations-node": { - "version": "0.70.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.70.1.tgz", - "integrity": "sha512-r8BKs0rHtBAzZViPIuzSD2eh65fOPau0NqVsca2sACuZ6LFGu6a+QMhqq7skXz+/OqKwFr/7/b6VsaNMS+zZpQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/instrumentation-amqplib": "^0.59.0", - "@opentelemetry/instrumentation-aws-lambda": "^0.64.0", - "@opentelemetry/instrumentation-aws-sdk": "^0.67.0", - "@opentelemetry/instrumentation-bunyan": "^0.57.0", - "@opentelemetry/instrumentation-cassandra-driver": "^0.57.0", - "@opentelemetry/instrumentation-connect": "^0.55.0", - "@opentelemetry/instrumentation-cucumber": "^0.28.0", - "@opentelemetry/instrumentation-dataloader": "^0.29.0", - "@opentelemetry/instrumentation-dns": "^0.55.0", - "@opentelemetry/instrumentation-express": "^0.60.0", - "@opentelemetry/instrumentation-fastify": "^0.56.0", - "@opentelemetry/instrumentation-fs": "^0.31.0", - "@opentelemetry/instrumentation-generic-pool": "^0.55.0", - "@opentelemetry/instrumentation-graphql": "^0.60.0", - "@opentelemetry/instrumentation-grpc": "^0.212.0", - "@opentelemetry/instrumentation-hapi": "^0.58.0", - "@opentelemetry/instrumentation-http": "^0.212.0", - "@opentelemetry/instrumentation-ioredis": "^0.60.0", - "@opentelemetry/instrumentation-kafkajs": "^0.21.0", - "@opentelemetry/instrumentation-knex": "^0.56.0", - "@opentelemetry/instrumentation-koa": "^0.60.0", - "@opentelemetry/instrumentation-lru-memoizer": "^0.56.0", - "@opentelemetry/instrumentation-memcached": "^0.55.0", - "@opentelemetry/instrumentation-mongodb": "^0.65.0", - "@opentelemetry/instrumentation-mongoose": "^0.58.0", - "@opentelemetry/instrumentation-mysql": "^0.58.0", - "@opentelemetry/instrumentation-mysql2": "^0.58.0", - "@opentelemetry/instrumentation-nestjs-core": "^0.58.0", - "@opentelemetry/instrumentation-net": "^0.56.0", - "@opentelemetry/instrumentation-openai": "^0.10.0", - "@opentelemetry/instrumentation-oracledb": "^0.37.0", - "@opentelemetry/instrumentation-pg": "^0.64.0", - "@opentelemetry/instrumentation-pino": "^0.58.0", - "@opentelemetry/instrumentation-redis": "^0.60.0", - "@opentelemetry/instrumentation-restify": "^0.57.0", - "@opentelemetry/instrumentation-router": "^0.56.0", - "@opentelemetry/instrumentation-runtime-node": "^0.25.0", - "@opentelemetry/instrumentation-socket.io": "^0.59.0", - "@opentelemetry/instrumentation-tedious": "^0.31.0", - "@opentelemetry/instrumentation-undici": "^0.22.0", - "@opentelemetry/instrumentation-winston": "^0.56.0", - "@opentelemetry/resource-detector-alibaba-cloud": "^0.33.2", - "@opentelemetry/resource-detector-aws": "^2.12.0", - "@opentelemetry/resource-detector-azure": "^0.20.0", - "@opentelemetry/resource-detector-container": "^0.8.3", - "@opentelemetry/resource-detector-gcp": "^0.47.0", - "@opentelemetry/resources": "^2.0.0", - "@opentelemetry/sdk-node": "^0.212.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.4.1", - "@opentelemetry/core": "^2.0.0" - } - }, - "node_modules/@opentelemetry/configuration": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/configuration/-/configuration-0.212.0.tgz", - "integrity": "sha512-D8sAY6RbqMa1W8lCeiaSL2eMCW2MF87QI3y+I6DQE1j+5GrDMwiKPLdzpa/2/+Zl9v1//74LmooCTCJBvWR8Iw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.5.1", - "yaml": "^2.0.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.9.0" - } - }, - "node_modules/@opentelemetry/context-async-hooks": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.5.1.tgz", - "integrity": "sha512-MHbu8XxCHcBn6RwvCt2Vpn1WnLMNECfNKYB14LI5XypcgH4IE0/DiVifVR9tAkwPMyLXN8dOoPJfya3IryLQVw==", - "license": "Apache-2.0", - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/core": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.5.1.tgz", - "integrity": "sha512-Dwlc+3HAZqpgTYq0MUyZABjFkcrKTePwuiFVLjahGD8cx3enqihmpAmdgNFO1R4m/sIe5afjJrA25Prqy4NXlA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/exporter-logs-otlp-grpc": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.212.0.tgz", - "integrity": "sha512-/0bk6fQG+eSFZ4L6NlckGTgUous/ib5+OVdg0x4OdwYeHzV3lTEo3it1HgnPY6UKpmX7ki+hJvxjsOql8rCeZA==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/grpc-js": "^1.14.3", - "@opentelemetry/core": "2.5.1", - "@opentelemetry/otlp-exporter-base": "0.212.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.212.0", - "@opentelemetry/otlp-transformer": "0.212.0", - "@opentelemetry/sdk-logs": "0.212.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/exporter-logs-otlp-http": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.212.0.tgz", - "integrity": "sha512-JidJasLwG/7M9RTxV/64xotDKmFAUSBc9SNlxI32QYuUMK5rVKhHNWMPDzC7E0pCAL3cu+FyiKvsTwLi2KqPYw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.212.0", - "@opentelemetry/core": "2.5.1", - "@opentelemetry/otlp-exporter-base": "0.212.0", - "@opentelemetry/otlp-transformer": "0.212.0", - "@opentelemetry/sdk-logs": "0.212.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/exporter-logs-otlp-proto": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.212.0.tgz", - "integrity": "sha512-RpKB5UVfxc7c6Ta1UaCrxXDTQ0OD7BCGT66a97Q5zR1x3+9fw4dSaiqMXT/6FAWj2HyFbem6Rcu1UzPZikGTWQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.212.0", - "@opentelemetry/core": "2.5.1", - "@opentelemetry/otlp-exporter-base": "0.212.0", - "@opentelemetry/otlp-transformer": "0.212.0", - "@opentelemetry/resources": "2.5.1", - "@opentelemetry/sdk-logs": "0.212.0", - "@opentelemetry/sdk-trace-base": "2.5.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/exporter-metrics-otlp-grpc": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.212.0.tgz", - "integrity": "sha512-/6Gqf9wpBq22XsomR1i0iPGnbQtCq2Vwnrq5oiDPjYSqveBdK1jtQbhGfmpK2mLLxk4cPDtD1ZEYdIou5K8EaA==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/grpc-js": "^1.14.3", - "@opentelemetry/core": "2.5.1", - "@opentelemetry/exporter-metrics-otlp-http": "0.212.0", - "@opentelemetry/otlp-exporter-base": "0.212.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.212.0", - "@opentelemetry/otlp-transformer": "0.212.0", - "@opentelemetry/resources": "2.5.1", - "@opentelemetry/sdk-metrics": "2.5.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/exporter-metrics-otlp-http": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.212.0.tgz", - "integrity": "sha512-8hgBw3aTTRpSTkU4b9MLf/2YVLnfWp+hfnLq/1Fa2cky+vx6HqTodo+Zv1GTIrAKMOOwgysOjufy0gTxngqeBg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.5.1", - "@opentelemetry/otlp-exporter-base": "0.212.0", - "@opentelemetry/otlp-transformer": "0.212.0", - "@opentelemetry/resources": "2.5.1", - "@opentelemetry/sdk-metrics": "2.5.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/exporter-metrics-otlp-proto": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.212.0.tgz", - "integrity": "sha512-C7I4WN+ghn3g7SnxXm2RK3/sRD0k/BYcXaK6lGU3yPjiM7a1M25MLuM6zY3PeVPPzzTZPfuS7+wgn/tHk768Xw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.5.1", - "@opentelemetry/exporter-metrics-otlp-http": "0.212.0", - "@opentelemetry/otlp-exporter-base": "0.212.0", - "@opentelemetry/otlp-transformer": "0.212.0", - "@opentelemetry/resources": "2.5.1", - "@opentelemetry/sdk-metrics": "2.5.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/exporter-prometheus": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.212.0.tgz", - "integrity": "sha512-hJFLhCJba5MW5QHexZMHZdMhBfNqNItxOsN0AZojwD1W2kU9xM+BEICowFGJFo/vNV+I2BJvTtmuKafeDSAo7Q==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.5.1", - "@opentelemetry/resources": "2.5.1", - "@opentelemetry/sdk-metrics": "2.5.1", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-grpc": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.212.0.tgz", - "integrity": "sha512-9xTuYWp8ClBhljDGAoa0NSsJcsxJsC9zCFKMSZJp1Osb9pjXCMRdA6fwXtlubyqe7w8FH16EWtQNKx/FWi+Ghw==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/grpc-js": "^1.14.3", - "@opentelemetry/core": "2.5.1", - "@opentelemetry/otlp-exporter-base": "0.212.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.212.0", - "@opentelemetry/otlp-transformer": "0.212.0", - "@opentelemetry/resources": "2.5.1", - "@opentelemetry/sdk-trace-base": "2.5.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-http": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.212.0.tgz", - "integrity": "sha512-v/0wMozNoiEPRolzC4YoPo4rAT0q8r7aqdnRw3Nu7IDN0CGFzNQazkfAlBJ6N5y0FYJkban7Aw5WnN73//6YlA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.5.1", - "@opentelemetry/otlp-exporter-base": "0.212.0", - "@opentelemetry/otlp-transformer": "0.212.0", - "@opentelemetry/resources": "2.5.1", - "@opentelemetry/sdk-trace-base": "2.5.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.212.0.tgz", - "integrity": "sha512-d1ivqPT0V+i0IVOOdzGaLqonjtlk5jYrW7ItutWzXL/Mk+PiYb59dymy/i2reot9dDnBFWfrsvxyqdutGF5Vig==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.5.1", - "@opentelemetry/otlp-exporter-base": "0.212.0", - "@opentelemetry/otlp-transformer": "0.212.0", - "@opentelemetry/resources": "2.5.1", - "@opentelemetry/sdk-trace-base": "2.5.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/exporter-zipkin": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-2.5.1.tgz", - "integrity": "sha512-Me6JVO7WqXGXsgr4+7o+B7qwKJQbt0c8WamFnxpkR43avgG9k/niTntwCaXiXUTjonWy0+61ZuX6CGzj9nn8CQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.5.1", - "@opentelemetry/resources": "2.5.1", - "@opentelemetry/sdk-trace-base": "2.5.1", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/instrumentation": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.212.0.tgz", - "integrity": "sha512-IyXmpNnifNouMOe0I/gX7ENfv2ZCNdYTF0FpCsoBcpbIHzk81Ww9rQTYTnvghszCg7qGrIhNvWC8dhEifgX9Jg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.212.0", - "import-in-the-middle": "^2.0.6", - "require-in-the-middle": "^8.0.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-amqplib": { - "version": "0.59.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.59.0.tgz", - "integrity": "sha512-xscSgOJA+GHphESDZxBHNk/zjNaEgoeufMwmiqYdL+qM27Xw3BbR9vN6Ucbq9dW6Y+oYUPgTTj17qf+Za4+uzg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.33.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-aws-lambda": { - "version": "0.64.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-lambda/-/instrumentation-aws-lambda-0.64.0.tgz", - "integrity": "sha512-vYhM/a8fG34/Dl/Q9gfv5Ih3OFPgqeyn79S8FN+Xs/QZw6h6L8a1lDa3CyigyicOXLCmVIM7Fc9vFD4BGqgGLA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/aws-lambda": "^8.10.155" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-aws-sdk": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-sdk/-/instrumentation-aws-sdk-0.67.0.tgz", - "integrity": "sha512-btpwJnZ2RBXDh/pTpfVpInpBu9Pedi+lbLKbt3naB344SggbbYnIdT7u8EzmGIApWi9EV91vw7hm896I7nESQA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.34.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-bunyan": { - "version": "0.57.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-bunyan/-/instrumentation-bunyan-0.57.0.tgz", - "integrity": "sha512-W4zLz1Y9ptCsdL+QMXR7xQaBHkJivLBmVlLCjUe23rX4V8E65fGAtlIJSKTKAfz4aEgtWgQAGMdkeqACwG0Caw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "^0.212.0", - "@opentelemetry/instrumentation": "^0.212.0", - "@types/bunyan": "1.8.11" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-cassandra-driver": { - "version": "0.57.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cassandra-driver/-/instrumentation-cassandra-driver-0.57.0.tgz", - "integrity": "sha512-xLwrK+XnN32IB5i6t/a2j+SVdjlq/BIgjpVRkke4HAsKjoSMy1GeSI+ZOiJffRLFb4MojcvH4RG2+nEg1uC6Zg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.37.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-connect": { - "version": "0.55.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.55.0.tgz", - "integrity": "sha512-UfGw7ubKKZBoTRjxi5KlfeECEaXZinS20RdRNlZE5tVF+O17hJOnrcGwAoQAHp6eYmxI2jW9IQ4t6450gnNF9g==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/connect": "3.4.38" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-cucumber": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cucumber/-/instrumentation-cucumber-0.28.0.tgz", - "integrity": "sha512-kim+bRxu4LZqKEyF2SgO01tgG88W+/iYltyP1XjT31FIXzlBjzQpwtSLLM8byayO85mcZIBha54WSNFDLM/7qQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/instrumentation-dataloader": { - "version": "0.29.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.29.0.tgz", - "integrity": "sha512-220WjRb1G1UiAKbVblSMxwxxFdpyB4wj1XYIO9BJs5r62Azj2dL5fyZiXK3/WO6wB3uLul9R946iKI1bpPxktQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-dns": { - "version": "0.55.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dns/-/instrumentation-dns-0.55.0.tgz", - "integrity": "sha512-cfWLaFi22V+sQrKY7t6QroYzT3kO9m3PpkN1OXYmuCyfwxQaXOVlF8NSAHtua/RQYw0aQl+2fe6JOWyJdEZiwA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-express": { - "version": "0.60.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.60.0.tgz", - "integrity": "sha512-KghHCDqKq0D7iuPIVCuPSXut5WVAI6uwKcPrhwTUJL5VE2LC18id2vKoiAm1V8XvVlgIGAiECtEvbrFwkTCj3g==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-fastify": { - "version": "0.56.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.56.0.tgz", - "integrity": "sha512-zotOPoZsWtMF47BjottK23XaaBSmVuwG5D/R3FlGfAAwMNFoDR3IY1OGO9v9KfOU/1/xDVkxsQ22NFfu9lE8aA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-fs": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.31.0.tgz", - "integrity": "sha512-C7tdXGDnkMgLVlE79VSekB+Y+P345zKUigvFMs5M7U0GIYA8ERx3FS0aAcY/ICIq9YwRmH2uuMb++Br5M2vNUg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.212.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-generic-pool": { - "version": "0.55.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.55.0.tgz", - "integrity": "sha512-7hWiyLbEX/dIS4LZy/h8VaAQPs8oBeEqsrysDWbos0b9PF414L6Rsbi2um/omtxIs+GTvsbuqDscWigeaxyWdA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-graphql": { - "version": "0.60.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.60.0.tgz", - "integrity": "sha512-XPATrmxAd2tFCsYbJ3eVIXt+gyvMKjc36QQuQxjtssMnAbw006Le9b5lKs7WXik7ItOpM1exATi1aDdOcCjRRg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-grpc": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-grpc/-/instrumentation-grpc-0.212.0.tgz", - "integrity": "sha512-r1t7LNKWVhSQMUrBdDJtooFmmLZ93kGuFixqeXPoUP8W+chJCxhey9l0c0+L3xriNdyB7TzvkKHhPXUDevgVEA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "0.212.0", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-hapi": { - "version": "0.58.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.58.0.tgz", - "integrity": "sha512-reuRApR2KHm2VsfyDgsrLhNE+IOy4uIU6n3oMjUleReHacEEZmf4vXxdt4/qcmJ6GoUXnRN2AOu3s5N3pMrgYA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-http": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.212.0.tgz", - "integrity": "sha512-t2nt16Uyv9irgR+tqnX96YeToOStc3X5js7Ljn3EKlI2b4Fe76VhMkTXtsTQ0aId6AsYgefrCRnXSCo/Fn/vww==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.5.1", - "@opentelemetry/instrumentation": "0.212.0", - "@opentelemetry/semantic-conventions": "^1.29.0", - "forwarded-parse": "2.1.2" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-ioredis": { - "version": "0.60.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.60.0.tgz", - "integrity": "sha512-R+nnbPD9l2ruzu248qM3YDWzpdmWVaFFFv08lQqsc0EP4pT/B1GGUg06/tHOSo3L5njB2eejwyzpkvJkjaQEMA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/redis-common": "^0.38.2", - "@opentelemetry/semantic-conventions": "^1.33.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-kafkajs": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.21.0.tgz", - "integrity": "sha512-lkLrILnKGO7SHw1xPJnuGx2S4XwbKmQiJyzUGuEImRoU/6Gj0Nka0lkbeRd4ANN20dxr/mLdXIsUsk6DzTrX6A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.30.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-knex": { - "version": "0.56.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.56.0.tgz", - "integrity": "sha512-pKqtY5lbAQ70MC5K/BJeAA1t2gAUlRBZBAJ5ergRUNs5jw8zbdOXEZOLztiuNvQqD2z4a9N0Tkde9JMFm2pKMQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.33.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-koa": { - "version": "0.60.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.60.0.tgz", - "integrity": "sha512-UOmu2y2LHgPzKsm9xd0sCQJimr11YP4MKFc190Do1ufd8qds7Zd5BI3f6TudqYhH9dUIhojsQyUaS6K4nv5FsQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.36.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.9.0" - } - }, - "node_modules/@opentelemetry/instrumentation-lru-memoizer": { - "version": "0.56.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.56.0.tgz", - "integrity": "sha512-vXtOValhKRgWA9tLAiTU3P37Q31OveRuM2N5iLSVHl4GzkMBQ5p50A9kSKvt5gReL6BzFDXPCM9ItJiAhSS2KQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-memcached": { - "version": "0.55.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-memcached/-/instrumentation-memcached-0.55.0.tgz", - "integrity": "sha512-kdhW/j5X+vNCAvHVc50PZfvE7diUScg1ZkBaNFRygY3Z6IUjgPLR0luWQMDPSFun6AVo1HaMDPxbUqJrot6qrA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.33.0", - "@types/memcached": "^2.2.6" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-mongodb": { - "version": "0.65.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.65.0.tgz", - "integrity": "sha512-hOAJRs5vrY7fZolSYUXmf29Y+HFDHWrek0DeLq82uwMPjPSda7h6oumQnqEX5olzw357q/QG39/uJdkclJ/JUg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.33.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-mongoose": { - "version": "0.58.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.58.0.tgz", - "integrity": "sha512-3L0Fqo1y2oreISFPWaqdt/bg3NhLgrkn5U/E/9RNG1QaM81drTMBCHseMY1q8SlejjE43ZWOy+0KbmRBlUPJ+g==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.33.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-mysql": { - "version": "0.58.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.58.0.tgz", - "integrity": "sha512-wZDrBCL3WfJclV6KywWVV3/B2ZiUYmDQdgyu3pq4jK/5qSfoDmezHzT/Nayln5MVVWMAGXIMLrCj8BKa6jaKQQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.33.0", - "@types/mysql": "2.15.27" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-mysql2": { - "version": "0.58.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.58.0.tgz", - "integrity": "sha512-EubjV1XZb7XHrENqF7TW2lnah+KN0LddMneKNAB8PjGVKL5lJkVV/vhJ6EIcUNn9nCWmAwZ3GRcFVEDKCnyXfQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.33.0", - "@opentelemetry/sql-common": "^0.41.2" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-nestjs-core": { - "version": "0.58.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.58.0.tgz", - "integrity": "sha512-0lE9oW8j6nmvBHJoOxIQgKzMQQYNfX1nhiWZdXD0sNAMFsWBtvECWS7NAPSroKrEP53I04TcHCyyhcK4I9voXg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.30.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-net": { - "version": "0.56.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-net/-/instrumentation-net-0.56.0.tgz", - "integrity": "sha512-h69x7U6f86mP3gGWWTaMkQZk0K3tBvpVMIU7E0q2kkVw6eZ5TqFm9rkaEy38moQmixiDFQ9j/2/cwxG9P7ZEeA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.33.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-openai": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-openai/-/instrumentation-openai-0.10.0.tgz", - "integrity": "sha512-0lV2zxge2mMaruVCw/bmypWVu+aJ76rc0HBvAVFCPUI3zzJdgBZJZafGIHZ1IB2F6VvrDFL+JstEnle6V8brvA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "^0.212.0", - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.36.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-oracledb": { - "version": "0.37.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-oracledb/-/instrumentation-oracledb-0.37.0.tgz", - "integrity": "sha512-OzMghtAEAEkXlkUrZI4QcXSZq0MILeU6WC0/N5+1MSkuIkruIeaRw99/RtyS2of8vlPDa8XbbXl32Q1RM3wSyg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.34.0", - "@types/oracledb": "6.5.2" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-pg": { - "version": "0.64.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.64.0.tgz", - "integrity": "sha512-NbfB/rlfsRI3zpTjnbvJv3qwuoGLsN8FxR/XoI+ZTn1Rs62x1IenO+TSSvk4NO+7FlXpd2MiOe8LT/oNbydHGA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.34.0", - "@opentelemetry/sql-common": "^0.41.2", - "@types/pg": "8.15.6", - "@types/pg-pool": "2.0.7" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-pino": { - "version": "0.58.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pino/-/instrumentation-pino-0.58.0.tgz", - "integrity": "sha512-rgy+tA7cDjuSq6dXAO40OiYP25azIDHMBtxG3RzSmCBVEYdjggl6btyuLVasX6VkOOhP2gf6PBuLMNxVwaIqAw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "^0.212.0", - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.212.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-redis": { - "version": "0.60.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.60.0.tgz", - "integrity": "sha512-Ea/GffmmzIVHc9geaMjT94IR7poVZzIv4Kk/Lw0tbxGD3cBYcMUsLFVajKxpZsE1NRCECFpidAWeifCIKD0inw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/redis-common": "^0.38.2", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-restify": { - "version": "0.57.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-restify/-/instrumentation-restify-0.57.0.tgz", - "integrity": "sha512-kO6MsZFU+RdXOKhsKw8SOSBYGYCdFSlza+mpBQRl1DQmveZcnidchv4V5JQPtNgHxCGH+1n3hDpLdxdGUbJPNA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-router": { - "version": "0.56.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-router/-/instrumentation-router-0.56.0.tgz", - "integrity": "sha512-PHECDGQElLazI/QbHU16C5m9fDC7DGJk+jLIwO5ca6bcp7bXhUPPUTT78l7da2pDsrz4mhv5ytYNZmBbW/Q3rA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-runtime-node": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-runtime-node/-/instrumentation-runtime-node-0.25.0.tgz", - "integrity": "sha512-XaCmwBSui5KeTn8M6OzaEn1rEsNWtUkjuc1ylg0tqQTLHibNQ0n7f8v4zdF6x/nBV1OnsiYlN8RLHauGemv/TA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-socket.io": { - "version": "0.59.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-socket.io/-/instrumentation-socket.io-0.59.0.tgz", - "integrity": "sha512-71DnM/FEqH0PjvU2uZvzWJeaGyVIy3rJKk8rZrxg/aS2QT3qLGb+UPL/B+1vOw4pzDPn4papLTSMpLVF9G8uvw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-tedious": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.31.0.tgz", - "integrity": "sha512-HoF2EtcyP3JR4R3jLPHohZ9lFcj1QLJyGmFfLKDTvUUjPiFuK4XZ6L1OV9HhaqvN0xY+tWKfNdCPS3r33rd0Xw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.33.0", - "@types/tedious": "^4.0.14" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-undici": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.22.0.tgz", - "integrity": "sha512-yb6vEWUPOrD5i7yR1XceEEqiVHbMgr5YnUPnom5eQVCjvrTkEVswyrf9i+vvJR+28wrNqILIIphWgOOx6BjnTQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.212.0", - "@opentelemetry/semantic-conventions": "^1.24.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.7.0" - } - }, - "node_modules/@opentelemetry/instrumentation-winston": { - "version": "0.56.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-winston/-/instrumentation-winston-0.56.0.tgz", - "integrity": "sha512-ITIA0Qe61CQ6FQU/bN23pNBvJ+5U0ofoASMOOYrODtXyV9wI267AigNTTwDmv2Myt8dPEFvvVFJZKhiZLIpehA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "^0.212.0", - "@opentelemetry/instrumentation": "^0.212.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/otlp-exporter-base": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.212.0.tgz", - "integrity": "sha512-HoMv5pQlzbuxiMS0hN7oiUtg8RsJR5T7EhZccumIWxYfNo/f4wFc7LPDfFK6oHdG2JF/+qTocfqIHoom+7kLpw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.5.1", - "@opentelemetry/otlp-transformer": "0.212.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/otlp-grpc-exporter-base": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.212.0.tgz", - "integrity": "sha512-YidOSlzpsun9uw0iyIWrQp6HxpMtBlECE3tiHGAsnpEqJWbAUWcMnIffvIuvTtTQ1OyRtwwaE79dWSQ8+eiB7g==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/grpc-js": "^1.14.3", - "@opentelemetry/core": "2.5.1", - "@opentelemetry/otlp-exporter-base": "0.212.0", - "@opentelemetry/otlp-transformer": "0.212.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.212.0.tgz", - "integrity": "sha512-bj7zYFOg6Db7NUwsRZQ/WoVXpAf41WY2gsd3kShSfdpZQDRKHWJiRZIg7A8HvWsf97wb05rMFzPbmSHyjEl9tw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.212.0", - "@opentelemetry/core": "2.5.1", - "@opentelemetry/resources": "2.5.1", - "@opentelemetry/sdk-logs": "0.212.0", - "@opentelemetry/sdk-metrics": "2.5.1", - "@opentelemetry/sdk-trace-base": "2.5.1", - "protobufjs": "8.0.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/protobufjs": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-8.0.0.tgz", - "integrity": "sha512-jx6+sE9h/UryaCZhsJWbJtTEy47yXoGNYI4z8ZaRncM0zBKeRqjO2JEcOUYwrYGb1WLhXM1FfMzW3annvFv0rw==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@opentelemetry/propagator-b3": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-2.5.1.tgz", - "integrity": "sha512-AU6sZgunZrZv/LTeHP+9IQsSSH5p3PtOfDPe8VTdwYH69nZCfvvvXehhzu+9fMW2mgJMh5RVpiH8M9xuYOu5Dg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.5.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/propagator-jaeger": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-2.5.1.tgz", - "integrity": "sha512-8+SB94/aSIOVGDUPRFSBRHVUm2A8ye1vC6/qcf/D+TF4qat7PC6rbJhRxiUGDXZtMtKEPM/glgv5cBGSJQymSg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.5.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/redis-common": { - "version": "0.38.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.38.2.tgz", - "integrity": "sha512-1BCcU93iwSRZvDAgwUxC/DV4T/406SkMfxGqu5ojc3AvNI+I9GhV7v0J1HljsczuuhcnFLYqD5VmwVXfCGHzxA==", - "license": "Apache-2.0", - "engines": { - "node": "^18.19.0 || >=20.6.0" - } - }, - "node_modules/@opentelemetry/resource-detector-alibaba-cloud": { - "version": "0.33.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-alibaba-cloud/-/resource-detector-alibaba-cloud-0.33.2.tgz", - "integrity": "sha512-EaS54zwYmOg9Ttc79juaktpCBYqyh2IquXl534sLls+c1/pc8LZfWPMqytFt+iBvSPQ6ajraUnvi6cun4AhSjQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/resources": "^2.0.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/resource-detector-aws": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-aws/-/resource-detector-aws-2.12.0.tgz", - "integrity": "sha512-VelueKblsnQEiBVqEYcvM9VEb+B8zN6nftltdO9HAD7qi/OlicP4z/UGJ9EeW2m++WabdMoj0G3QVL8YV0P9tw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/resources": "^2.0.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/resource-detector-azure": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-azure/-/resource-detector-azure-0.20.0.tgz", - "integrity": "sha512-iRy+O2cB6DOlQ/OONaK+L8Cp8nLS89dZVRp6KgnFAfzykXuq9Ws/ygJKcU3CCmjkgY5j2Vk3uVTre/E35bWhYg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/resources": "^2.0.0", - "@opentelemetry/semantic-conventions": "^1.37.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/resource-detector-container": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-container/-/resource-detector-container-0.8.3.tgz", - "integrity": "sha512-5J0JP2cy655rBKM9Doz26ffO3rG+Xqm7OXeNXkckzmc3JmL6Bj3dPBKugPYsfemhEIqtf7INH9UmPQqTMuWoHg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/resources": "^2.0.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/resource-detector-gcp": { - "version": "0.47.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.47.0.tgz", - "integrity": "sha512-57T/kRVdU0ch1P4KPEkmU2b5mWNlUs8hHgqrBYVF+fNZMc1jMdL1mANZhEzoLtWKIeoCEy+57Itt7RkXAYNJiQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/resources": "^2.0.0", - "gcp-metadata": "^8.0.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/resources": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.5.1.tgz", - "integrity": "sha512-BViBCdE/GuXRlp9k7nS1w6wJvY5fnFX5XvuEtWsTAOQFIO89Eru7lGW3WbfbxtCuZ/GbrJfAziXG0w0dpxL7eQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.5.1", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-logs": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.212.0.tgz", - "integrity": "sha512-qglb5cqTf0mOC1sDdZ7nfrPjgmAqs2OxkzOPIf2+Rqx8yKBK0pS7wRtB1xH30rqahBIut9QJDbDePyvtyqvH/Q==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.212.0", - "@opentelemetry/core": "2.5.1", - "@opentelemetry/resources": "2.5.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.4.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-metrics": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.5.1.tgz", - "integrity": "sha512-RKMn3QKi8nE71ULUo0g/MBvq1N4icEBo7cQSKnL3URZT16/YH3nSVgWegOjwx7FRBTrjOIkMJkCUn/ZFIEfn4A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.5.1", - "@opentelemetry/resources": "2.5.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.9.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-node": { - "version": "0.212.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.212.0.tgz", - "integrity": "sha512-tJzVDk4Lo44MdgJLlP+gdYdMnjxSNsjC/IiTxj5CFSnsjzpHXwifgl3BpUX67Ty3KcdubNVfedeBc/TlqHXwwg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.212.0", - "@opentelemetry/configuration": "0.212.0", - "@opentelemetry/context-async-hooks": "2.5.1", - "@opentelemetry/core": "2.5.1", - "@opentelemetry/exporter-logs-otlp-grpc": "0.212.0", - "@opentelemetry/exporter-logs-otlp-http": "0.212.0", - "@opentelemetry/exporter-logs-otlp-proto": "0.212.0", - "@opentelemetry/exporter-metrics-otlp-grpc": "0.212.0", - "@opentelemetry/exporter-metrics-otlp-http": "0.212.0", - "@opentelemetry/exporter-metrics-otlp-proto": "0.212.0", - "@opentelemetry/exporter-prometheus": "0.212.0", - "@opentelemetry/exporter-trace-otlp-grpc": "0.212.0", - "@opentelemetry/exporter-trace-otlp-http": "0.212.0", - "@opentelemetry/exporter-trace-otlp-proto": "0.212.0", - "@opentelemetry/exporter-zipkin": "2.5.1", - "@opentelemetry/instrumentation": "0.212.0", - "@opentelemetry/propagator-b3": "2.5.1", - "@opentelemetry/propagator-jaeger": "2.5.1", - "@opentelemetry/resources": "2.5.1", - "@opentelemetry/sdk-logs": "0.212.0", - "@opentelemetry/sdk-metrics": "2.5.1", - "@opentelemetry/sdk-trace-base": "2.5.1", - "@opentelemetry/sdk-trace-node": "2.5.1", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-trace-base": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.5.1.tgz", - "integrity": "sha512-iZH3Gw8cxQn0gjpOjJMmKLd9GIaNh/E3v3ST67vyzLSxHBs14HsG4dy7jMYyC5WXGdBVEcM7U/XTF5hCQxjDMw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.5.1", - "@opentelemetry/resources": "2.5.1", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-trace-node": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.5.1.tgz", - "integrity": "sha512-9lopQ6ZoElETOEN0csgmtEV5/9C7BMfA7VtF4Jape3i954b6sTY2k3Xw3CxUTKreDck/vpAuJM+EDo4zheUw+A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/context-async-hooks": "2.5.1", - "@opentelemetry/core": "2.5.1", - "@opentelemetry/sdk-trace-base": "2.5.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.39.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.39.0.tgz", - "integrity": "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/sql-common": { - "version": "0.41.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.41.2.tgz", - "integrity": "sha512-4mhWm3Z8z+i508zQJ7r6Xi7y4mmoJpdvH0fZPFRkWrdp5fq7hhZ2HhYokEOLkfqSMgPR4Z9EyB3DBkbKGOqZiQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.1.0" - } - }, - "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/@pkgr/core": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", - "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/pkgr" - } - }, - "node_modules/@prisma/client": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.19.2.tgz", - "integrity": "sha512-gR2EMvfK/aTxsuooaDA32D8v+us/8AAet+C3J1cc04SW35FPdZYgLF+iN4NDLUgAaUGTKdAB0CYenu1TAgGdMg==", - "hasInstallScript": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "peerDependencies": { - "prisma": "*", - "typescript": ">=5.1.0" - }, - "peerDependenciesMeta": { - "prisma": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/@prisma/config": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.19.2.tgz", - "integrity": "sha512-kadBGDl+aUswv/zZMk9Mx0C8UZs1kjao8H9/JpI4Wh4SHZaM7zkTwiKn/iFLfRg+XtOAo/Z/c6pAYhijKl0nzQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "c12": "3.1.0", - "deepmerge-ts": "7.1.5", - "effect": "3.18.4", - "empathic": "2.0.0" - } - }, - "node_modules/@prisma/debug": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.19.2.tgz", - "integrity": "sha512-lFnEZsLdFLmEVCVNdskLDCL8Uup41GDfU0LUfquw+ercJC8ODTuL0WNKgOKmYxCJVvFwf0OuZBzW99DuWmoH2A==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/@prisma/engines": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.19.2.tgz", - "integrity": "sha512-TTkJ8r+uk/uqczX40wb+ODG0E0icVsMgwCTyTHXehaEfb0uo80M9g1aW1tEJrxmFHeOZFXdI2sTA1j1AgcHi4A==", - "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "6.19.2", - "@prisma/engines-version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", - "@prisma/fetch-engine": "6.19.2", - "@prisma/get-platform": "6.19.2" - } - }, - "node_modules/@prisma/engines-version": { - "version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7.tgz", - "integrity": "sha512-03bgb1VD5gvuumNf+7fVGBzfpJPjmqV423l/WxsWk2cNQ42JD0/SsFBPhN6z8iAvdHs07/7ei77SKu7aZfq8bA==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/@prisma/fetch-engine": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.19.2.tgz", - "integrity": "sha512-h4Ff4Pho+SR1S8XerMCC12X//oY2bG3Iug/fUnudfcXEUnIeRiBdXHFdGlGOgQ3HqKgosTEhkZMvGM9tWtYC+Q==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "6.19.2", - "@prisma/engines-version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", - "@prisma/get-platform": "6.19.2" - } - }, - "node_modules/@prisma/get-platform": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.19.2.tgz", - "integrity": "sha512-PGLr06JUSTqIvztJtAzIxOwtWKtJm5WwOG6xpsgD37Rc84FpfUBGLKz65YpJBGtkRQGXTYEFie7pYALocC3MtA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "6.19.2" - } - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", - "license": "BSD-3-Clause" - }, - "node_modules/@redis/bloom": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz", - "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/client": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.1.tgz", - "integrity": "sha512-/KCsg3xSlR+nCK8/8ZYSknYxvXHwubJrU82F3Lm1Fp6789VQ0/3RJKfsmRXjqfaTA++23CvC3hqmqe/2GEt6Kw==", - "license": "MIT", - "dependencies": { - "cluster-key-slot": "1.1.2", - "generic-pool": "3.9.0", - "yallist": "4.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@redis/client/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/@redis/graph": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.1.tgz", - "integrity": "sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/json": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.7.tgz", - "integrity": "sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/search": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.2.0.tgz", - "integrity": "sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/time-series": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.1.0.tgz", - "integrity": "sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@scure/base": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", - "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", - "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", - "license": "MIT", - "dependencies": { - "@noble/curves": "~1.4.0", - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.4.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32/node_modules/@scure/base": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", - "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", - "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39/node_modules/@scure/base": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", - "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@sentry/core": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz", - "integrity": "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==", - "license": "BSD-3-Clause", - "dependencies": { - "@sentry/hub": "5.30.0", - "@sentry/minimal": "5.30.0", - "@sentry/types": "5.30.0", - "@sentry/utils": "5.30.0", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/core/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "license": "0BSD" - }, - "node_modules/@sentry/hub": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz", - "integrity": "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==", - "license": "BSD-3-Clause", - "dependencies": { - "@sentry/types": "5.30.0", - "@sentry/utils": "5.30.0", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/hub/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "license": "0BSD" - }, - "node_modules/@sentry/minimal": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz", - "integrity": "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==", - "license": "BSD-3-Clause", - "dependencies": { - "@sentry/hub": "5.30.0", - "@sentry/types": "5.30.0", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/minimal/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "license": "0BSD" - }, - "node_modules/@sentry/node": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz", - "integrity": "sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==", - "license": "BSD-3-Clause", - "dependencies": { - "@sentry/core": "5.30.0", - "@sentry/hub": "5.30.0", - "@sentry/tracing": "5.30.0", - "@sentry/types": "5.30.0", - "@sentry/utils": "5.30.0", - "cookie": "^0.4.1", - "https-proxy-agent": "^5.0.0", - "lru_map": "^0.3.3", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/node/node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@sentry/node/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "license": "0BSD" - }, - "node_modules/@sentry/tracing": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz", - "integrity": "sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==", - "license": "MIT", - "dependencies": { - "@sentry/hub": "5.30.0", - "@sentry/minimal": "5.30.0", - "@sentry/types": "5.30.0", - "@sentry/utils": "5.30.0", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/tracing/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "license": "0BSD" - }, - "node_modules/@sentry/types": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", - "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/utils": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz", - "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==", - "license": "BSD-3-Clause", - "dependencies": { - "@sentry/types": "5.30.0", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/utils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "license": "0BSD" - }, - "node_modules/@shikijs/engine-oniguruma": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.23.0.tgz", - "integrity": "sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.23.0", - "@shikijs/vscode-textmate": "^10.0.2" - } - }, - "node_modules/@shikijs/langs": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.23.0.tgz", - "integrity": "sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.23.0" - } - }, - "node_modules/@shikijs/themes": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.23.0.tgz", - "integrity": "sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.23.0" - } - }, - "node_modules/@shikijs/types": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.23.0.tgz", - "integrity": "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" - } - }, - "node_modules/@shikijs/vscode-textmate": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", - "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", - "dev": true, - "license": "MIT" - }, - "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/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/commons/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/@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/@so-ric/colorspace/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/@so-ric/colorspace/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/@so-ric/colorspace/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/@so-ric/colorspace/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/@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/@standard-schema/spec": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", - "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tokenizer/inflate": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.2.7.tgz", - "integrity": "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "fflate": "^0.8.2", - "token-types": "^6.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", - "license": "MIT" - }, - "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==", - "dev": 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==", - "dev": 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==", - "dev": 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==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/aws-lambda": { - "version": "8.10.160", - "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.160.tgz", - "integrity": "sha512-uoO4QVQNWFPJMh26pXtmtrRfGshPUSpMZGUyUQY20FhfHEElEBOPKgVmFs1z+kbpyBsRs2JnoOPT7++Z4GA9pA==", - "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/bunyan": { - "version": "1.8.11", - "resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.11.tgz", - "integrity": "sha512-758fRH7umIMk5qt5ELmRMff4mLDlN+xyYzC+dkPTdKwbSkJFvz6xwyScrytPU0QIBbRRwbiE8/BIg8bpajerNQ==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/compression": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.8.1.tgz", - "integrity": "sha512-kCFuWS0ebDbmxs0AXYn6e2r2nrGAb5KwQhknjSPSPgJcGd8+HVSILlUyFhGqML2gk39HcG7D1ydW9/qpYkN00Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*", - "@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==", - "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/crypto-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz", - "integrity": "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/docker-modem": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/docker-modem/-/docker-modem-3.0.6.tgz", - "integrity": "sha512-yKpAGEuKRSS8wwx0joknWxsmLha78wNMe9R2S3UNsVOkZded8UqOrV8KoeDXoXsjndxwyF3eIhyClGbO1SEhEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/ssh2": "*" - } - }, - "node_modules/@types/dockerode": { - "version": "3.3.47", - "resolved": "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.3.47.tgz", - "integrity": "sha512-ShM1mz7rCjdssXt7Xz0u1/R2BJC7piWa3SJpUBiVjCf2A3XNn4cP6pUVaD8bLanpPVVn4IKzJuw3dOvkJ8IbYw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/docker-modem": "*", - "@types/node": "*", - "@types/ssh2": "*" - } - }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/express": { - "version": "4.17.25", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", - "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "^1" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.8", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", - "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/file-type": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/@types/file-type/-/file-type-10.6.0.tgz", - "integrity": "sha512-qn06Cjx7HZDMmDIqMn+smKr7JYQMVXoHqwMC2vdg19CxGpL0Q6KwuvnVEkws2sH5wqrWXExmvuztXtWSHs3MBw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "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/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "@types/ms": "*", - "@types/node": "*" - } - }, - "node_modules/@types/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-RDvF6wTulMPjrNdCoYRC8gNR880JNGT8uB+REUpC2Ns4pRqQJhGz90wh7rgdXDPpCczF3VGktDuFGVnz8zP7HA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/luxon": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.4.2.tgz", - "integrity": "sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==", - "license": "MIT" - }, - "node_modules/@types/memcached": { - "version": "2.2.10", - "resolved": "https://registry.npmjs.org/@types/memcached/-/memcached-2.2.10.tgz", - "integrity": "sha512-AM9smvZN55Gzs2wRrqeMHVP7KE8KWgCJO/XL5yCly2xF6EKa4YlbpK+cLSAH4NG/Ah64HrlegmGqW8kYws7Vxg==", - "license": "MIT", - "dependencies": { - "@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/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", - "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==", - "license": "MIT" - }, - "node_modules/@types/multer": { - "version": "1.4.13", - "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.13.tgz", - "integrity": "sha512-bhhdtPw7JqCiEfC9Jimx5LqX9BDIPJEh2q/fQ4bqbBPtyEZYr3cvF22NwG0DmPZNYA0CAf2CnqDB4KIGGpJcaw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/mysql": { - "version": "2.15.27", - "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.27.tgz", - "integrity": "sha512-YfWiV16IY0OeBfBCk8+hXKmdTKrKlwKN1MNKAPBu5JYxLwBEZl7QzeEpGnlZb3VMGJrrGmB84gXiH+ofs/TezA==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "20.19.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", - "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/nodemailer": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-7.0.11.tgz", - "integrity": "sha512-E+U4RzR2dKrx+u3N4DlsmLaDC6mMZOM/TPROxA0UAPiTgI0y4CEFBmZE+coGWTjakDriRsXG368lNk1u9Q0a2g==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/oracledb": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@types/oracledb/-/oracledb-6.5.2.tgz", - "integrity": "sha512-kK1eBS/Adeyis+3OlBDMeQQuasIDLUYXsi2T15ccNJ0iyUpQ4xDF7svFu3+bGVrI0CMBUclPciz+lsQR3JX3TQ==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/passport": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz", - "integrity": "sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/passport-jwt": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-3.0.13.tgz", - "integrity": "sha512-fjHaC6Bv8EpMMqzTnHP32SXlZGaNfBPC/Po5dmRGYi2Ky7ljXPbGnOy+SxZqa6iZvFgVhoJ1915Re3m93zmcfA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*", - "@types/jsonwebtoken": "*", - "@types/passport-strategy": "*" - } - }, - "node_modules/@types/passport-local": { - "version": "1.0.38", - "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.38.tgz", - "integrity": "sha512-nsrW4A963lYE7lNTv9cr5WmiUD1ibYJvWrpE13oxApFsRt77b0RdtZvKbCdNIY4v/QZ6TRQWaDDEwV1kCTmcXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*", - "@types/passport": "*", - "@types/passport-strategy": "*" - } - }, - "node_modules/@types/passport-strategy": { - "version": "0.2.38", - "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz", - "integrity": "sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*", - "@types/passport": "*" - } - }, - "node_modules/@types/pg": { - "version": "8.15.6", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.15.6.tgz", - "integrity": "sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ==", - "license": "MIT", - "dependencies": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^2.2.0" - } - }, - "node_modules/@types/pg-pool": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.7.tgz", - "integrity": "sha512-U4CwmGVQcbEuqpyju8/ptOKg6gEC+Tqsvj2xS9o1g71bUh8twxnC6ZL5rZKCsGN0iyH0CwgUyc9VR5owNQF9Ng==", - "license": "MIT", - "dependencies": { - "@types/pg": "*" - } - }, - "node_modules/@types/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", - "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/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": "1.15.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", - "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "<1" - } - }, - "node_modules/@types/serve-static/node_modules/@types/send": { - "version": "0.17.6", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", - "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/ssh2": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.15.5.tgz", - "integrity": "sha512-N1ASjp/nXH3ovBHddRJpli4ozpk6UdDYIX4RJWFa9L1YKnzdhTlVmiGHm4DZnj/jLbqZpes4aeR30EFGQtvhQQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "^18.11.18" - } - }, - "node_modules/@types/ssh2-streams": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/@types/ssh2-streams/-/ssh2-streams-0.1.13.tgz", - "integrity": "sha512-faHyY3brO9oLEA0QlcO8N2wT7R0+1sHWZvQ+y3rMLwdY1ZyS1z0W3t65j9PqT4HmQ6ALzNe7RZlNuCNE0wBSWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/ssh2/node_modules/@types/node": { - "version": "18.19.130", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", - "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/ssh2/node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true, - "license": "MIT" - }, - "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": "2.0.16", - "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.16.tgz", - "integrity": "sha512-6c2ogktZ06tr2ENoZivgm7YnprnhYE4ZoXGMY+oA7IuAf17M8FWvujXZGmxLv8y0PTyts4x5A+erSwVUFA8XSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/superagent": "*" - } - }, - "node_modules/@types/tedious": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", - "integrity": "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "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/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/uuid": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", - "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/validator": { - "version": "13.15.10", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.10.tgz", - "integrity": "sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==", - "license": "MIT" - }, - "node_modules/@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "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/@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@willsoto/nestjs-prometheus": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@willsoto/nestjs-prometheus/-/nestjs-prometheus-6.0.2.tgz", - "integrity": "sha512-ePyLZYdIrOOdlOWovzzMisIgviXqhPVzFpSMKNNhn6xajhRHeBsjAzSdpxZTc6pnjR9hw1lNAHyKnKl7lAPaVg==", - "license": "Apache-2.0", - "peerDependencies": { - "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0", - "prom-client": "^15.0.0" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/abitype": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-0.7.1.tgz", - "integrity": "sha512-VBkRHTDZf9Myaek/dO3yMmOzB/y2s3Zo6nVU7yaw1G+TvCHAjwaJzNGN9yo4K5D8bU/VZXKP1EJpRhFr862PlQ==", - "license": "MIT", - "peerDependencies": { - "typescript": ">=4.9.4", - "zod": "^3 >=3.19.1" - }, - "peerDependenciesMeta": { - "zod": { - "optional": true - } - } - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "license": "MIT", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/accept-language-parser": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/accept-language-parser/-/accept-language-parser-1.5.0.tgz", - "integrity": "sha512-QhyTbMLYo0BBGg1aWbeMG4ekWtds/31BrEU+DONOg/7ax23vxpL03Pb7/zBmha2v7vdD3AyzZVWBVGEZxKOXWw==", - "license": "MIT" - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "license": "MIT", - "peerDependencies": { - "acorn": "^8" - } - }, - "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.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/adm-zip": { - "version": "0.4.16", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", - "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", - "license": "MIT", - "engines": { - "node": ">=0.3.0" - } - }, - "node_modules/aes-js": { - "version": "4.0.0-beta.5", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", - "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", - "license": "MIT" - }, - "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/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", - "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/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "license": "ISC", - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "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==", - "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==", - "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==", - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "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/archiver": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", - "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "archiver-utils": "^5.0.2", - "async": "^3.2.4", - "buffer-crc32": "^1.0.0", - "readable-stream": "^4.0.0", - "readdir-glob": "^1.1.2", - "tar-stream": "^3.0.0", - "zip-stream": "^6.0.1" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/archiver-utils": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", - "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", - "dev": true, - "license": "MIT", - "dependencies": { - "glob": "^10.0.0", - "graceful-fs": "^4.2.0", - "is-stream": "^2.0.1", - "lazystream": "^1.0.0", - "lodash": "^4.17.15", - "normalize-path": "^3.0.0", - "readable-stream": "^4.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/archiver-utils/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "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": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/archiver-utils/node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", - "dev": true, - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/archiver/node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true, - "license": "MIT" - }, - "node_modules/archiver/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "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": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/archiver/node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", - "dev": true, - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": 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==", - "license": "Python-2.0" - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" - }, - "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-timsort": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", - "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", - "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/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/async-hook-jl": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/async-hook-jl/-/async-hook-jl-1.7.6.tgz", - "integrity": "sha512-gFaHkFfSxTjvoxDMYqDuGHlcRyUuamF8s+ZTtJdDzqjws4mCt7v0vuV79/E2Wr2/riMQgtG4/yUtXWs1gZ7JMg==", - "license": "MIT", - "dependencies": { - "stack-chain": "^1.3.7" - }, - "engines": { - "node": "^4.7 || >=6.9 || >=7.3" - } - }, - "node_modules/async-lock": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.1.tgz", - "integrity": "sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==", - "dev": true, - "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.13.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz", - "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.11", - "form-data": "^4.0.5", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/b4a": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", - "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==", - "dev": true, - "license": "Apache-2.0", - "peerDependencies": { - "react-native-b4a": "*" - }, - "peerDependenciesMeta": { - "react-native-b4a": { - "optional": true - } - } - }, - "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-events": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", - "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", - "dev": true, - "license": "Apache-2.0", - "peerDependencies": { - "bare-abort-controller": "*" - }, - "peerDependenciesMeta": { - "bare-abort-controller": { - "optional": true - } - } - }, - "node_modules/bare-fs": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.5.2.tgz", - "integrity": "sha512-veTnRzkb6aPHOvSKIOy60KzURfBdUflr5VReI+NSaPL6xf+XLdONQgZgpYvUuZLVQ8dCqxpBAudaOM1+KpAUxw==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "bare-events": "^2.5.4", - "bare-path": "^3.0.0", - "bare-stream": "^2.6.4", - "bare-url": "^2.2.2", - "fast-fifo": "^1.3.2" - }, - "engines": { - "bare": ">=1.16.0" - }, - "peerDependencies": { - "bare-buffer": "*" - }, - "peerDependenciesMeta": { - "bare-buffer": { - "optional": true - } - } - }, - "node_modules/bare-os": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.2.tgz", - "integrity": "sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "engines": { - "bare": ">=1.14.0" - } - }, - "node_modules/bare-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", - "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "bare-os": "^3.0.1" - } - }, - "node_modules/bare-stream": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.7.0.tgz", - "integrity": "sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "streamx": "^2.21.0" - }, - "peerDependencies": { - "bare-buffer": "*", - "bare-events": "*" - }, - "peerDependenciesMeta": { - "bare-buffer": { - "optional": true - }, - "bare-events": { - "optional": true - } - } - }, - "node_modules/bare-url": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.3.2.tgz", - "integrity": "sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "bare-path": "^3.0.0" - } - }, - "node_modules/base32.js": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.0.1.tgz", - "integrity": "sha512-EGHIRiegFa62/SsA1J+Xs2tIzludPdzM064N9wjbiEgHnGnJ1V0WEpA4pEwCYT5nDvZk3ubf0shqaCS7k6xeUQ==", - "license": "MIT" - }, - "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.9.16", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.16.tgz", - "integrity": "sha512-KeUZdBuxngy825i8xvzaK1Ncnkx0tBmb3k8DkEuqjKRkmtvNTjey2ZsNeh8Dw4lfKvbCOu9oeNx2TKm2vHqcRw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, - "node_modules/bcrypt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz", - "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "node-addon-api": "^8.3.0", - "node-gyp-build": "^4.8.4" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bintrees": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz", - "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==", - "license": "MIT" - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bn.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", - "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==", - "license": "MIT" - }, - "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "~1.2.0", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "on-finished": "~2.4.1", - "qs": "~6.14.0", - "raw-body": "~2.5.3", - "type-is": "~1.6.18", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/boxen": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", - "license": "MIT", - "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.2", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "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==", - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", - "license": "MIT" - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "license": "ISC" - }, - "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": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "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": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-crc32": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", - "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "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/buildcheck": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.7.tgz", - "integrity": "sha512-lHblz4ahamxpTmnsk+MNTRWsjYKv965MwOrSJyeD588rR3Jcu7swE+0wN5F+PbL5cjgu/9ObkhfzEPuofEMwLA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/bull": { - "version": "4.16.5", - "resolved": "https://registry.npmjs.org/bull/-/bull-4.16.5.tgz", - "integrity": "sha512-lDsx2BzkKe7gkCYiT5Acj02DpTwDznl/VNN7Psn7M3USPG7Vs/BaClZJJTAG+ufAR9++N1/NiUTdaFBWDIl5TQ==", - "license": "MIT", - "dependencies": { - "cron-parser": "^4.9.0", - "get-port": "^5.1.1", - "ioredis": "^5.3.2", - "lodash": "^4.17.21", - "msgpackr": "^1.11.2", - "semver": "^7.5.2", - "uuid": "^8.3.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/bull/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "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/byline": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", - "integrity": "sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.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/c12": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", - "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": "^4.0.3", - "confbox": "^0.2.2", - "defu": "^6.1.4", - "dotenv": "^16.6.1", - "exsolve": "^1.0.7", - "giget": "^2.0.0", - "jiti": "^2.4.2", - "ohash": "^2.0.11", - "pathe": "^2.0.3", - "perfect-debounce": "^1.0.0", - "pkg-types": "^2.2.0", - "rc9": "^2.1.2" - }, - "peerDependencies": { - "magicast": "^0.3.5" - }, - "peerDependenciesMeta": { - "magicast": { - "optional": true - } - } - }, - "node_modules/c12/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/c12/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/c12/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/cache-manager": { - "version": "7.2.8", - "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-7.2.8.tgz", - "integrity": "sha512-0HDaDLBBY/maa/LmUVAr70XUOwsiQD+jyzCBjmUErYZUKdMS9dT59PqW59PpVqfGM7ve6H0J6307JTpkCYefHQ==", - "license": "MIT", - "dependencies": { - "@cacheable/utils": "^2.3.3", - "keyv": "^5.5.5" - } - }, - "node_modules/cache-manager-ioredis-yet": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cache-manager-ioredis-yet/-/cache-manager-ioredis-yet-2.1.2.tgz", - "integrity": "sha512-p/5D+ADvJaZjAs12fR5l0ZJ+rK2EqbCryFdrzsMj3K+lGwNoCjB33N6V397otgreB+iwK+lssBshpkJDodiyMQ==", - "deprecated": "With cache-manager v6 we now are using Keyv", - "license": "MIT", - "dependencies": { - "cache-manager": "*", - "ioredis": "^5.4.1", - "telejson": "^7.2.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/cache-manager-redis-store": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/cache-manager-redis-store/-/cache-manager-redis-store-3.0.1.tgz", - "integrity": "sha512-o560kw+dFqusC9lQJhcm6L2F2fMKobJ5af+FoR2PdnMVdpQ3f3Bz6qzvObTGyvoazQJxjQNWgMQeChP4vRTuXQ==", - "license": "MIT", - "dependencies": { - "redis": "^4.3.1" - }, - "engines": { - "node": ">= 16.18.0" - } - }, - "node_modules/cache-manager/node_modules/keyv": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", - "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", - "license": "MIT", - "dependencies": { - "@keyv/serialize": "^1.1.1" - } - }, - "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": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys/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.30001765", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001765.tgz", - "integrity": "sha512-LWcNtSyZrakjECqmpP4qdg0MMGdN368D7X8XvvAqOcqMv0RxnlqVKZl2V6/mBR68oYMxOZPLw/gO7DuisMHUvQ==", - "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==", - "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/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true, - "license": "MIT" - }, - "node_modules/check-disk-space": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/check-disk-space/-/check-disk-space-3.4.0.tgz", - "integrity": "sha512-drVkSqfwA+TvuEhFipiR1OC9boEGZL5RrWvVsOthdcvQNXyCCuKkEiTOTXZ7qxSf/GLwq4GvzfrQD/Wz325hgw==", - "license": "MIT", - "engines": { - "node": ">=16" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "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/chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0" - } - }, - "node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "license": "MIT" - }, - "node_modules/citty": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", - "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "consola": "^3.2.3" - } - }, - "node_modules/citty/node_modules/consola": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", - "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.18.0 || >=16.10.0" - } - }, - "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/class-transformer": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", - "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==", - "license": "MIT" - }, - "node_modules/class-validator": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.3.tgz", - "integrity": "sha512-rXXekcjofVN1LTOSw+u4u9WXVEUvNBVjORW154q/IdmYWy1nMbOU9aNtZB0t8m+FJQ9q91jlr2f9CwwUFdFMRA==", - "license": "MIT", - "dependencies": { - "@types/validator": "^13.15.3", - "libphonenumber-js": "^1.11.1", - "validator": "^13.15.20" - } - }, - "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", - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-table3": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", - "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/cli-truncate": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", - "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", - "dev": true, - "license": "MIT", - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/cli-truncate/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true, - "license": "MIT" - }, - "node_modules/cli-truncate/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate/node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 10" - } - }, - "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/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/cls-hooked": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/cls-hooked/-/cls-hooked-4.2.2.tgz", - "integrity": "sha512-J4Xj5f5wq/4jAvcdgoGsL3G103BtWpZrMo8NEinRltN+xpTZdI+M38pyQqhuFU/P792xkMFvnKSf+Lm81U1bxw==", - "license": "BSD-2-Clause", - "dependencies": { - "async-hook-jl": "^1.7.6", - "emitter-listener": "^1.0.1", - "semver": "^5.4.1" - }, - "engines": { - "node": "^4.7 || >=6.9 || >=7.3 || >=8.2.1" - } - }, - "node_modules/cls-hooked/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/cluster-key-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.10.0" - } - }, - "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": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - }, - "engines": { - "node": ">=12.5.0" - } - }, - "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": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", - "license": "MIT", - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true, - "license": "MIT" - }, - "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/command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", - "license": "MIT" - }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/comment-json": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.5.tgz", - "integrity": "sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-timsort": "^1.0.3", - "core-util-is": "^1.0.3", - "esprima": "^4.0.1", - "has-own-prop": "^2.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">= 6" - } - }, - "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/compress-commons": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", - "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "crc-32": "^1.2.0", - "crc32-stream": "^6.0.0", - "is-stream": "^2.0.1", - "normalize-path": "^3.0.0", - "readable-stream": "^4.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/compress-commons/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "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": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/compress-commons/node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", - "dev": true, - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "license": "MIT", - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compression": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", - "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "compressible": "~2.0.18", - "debug": "2.6.9", - "negotiator": "~0.6.4", - "on-headers": "~1.1.0", - "safe-buffer": "5.2.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/compression/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "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/confbox": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.4.tgz", - "integrity": "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/consola": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", - "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", - "license": "MIT" - }, - "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": "7.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", - "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/conventional-changelog-conventionalcommits": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz", - "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==", - "dev": true, - "license": "ISC", - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/conventional-commits-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", - "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-text-path": "^2.0.0", - "JSONStream": "^1.3.5", - "meow": "^12.0.1", - "split2": "^4.0.0" - }, - "bin": { - "conventional-commits-parser": "cli.mjs" - }, - "engines": { - "node": ">=16" - } - }, - "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/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/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, - "license": "MIT", - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.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": "5.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.1.0.tgz", - "integrity": "sha512-7PtBB+6FdsOvZyJtlF3hEPpACq7RQX6BVGsgC7/lfVXnKMvNCu/XY3ykreqG5w/rBNdu2z8LCIKoF3kpHHdHlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "jiti": "^1.21.6" - }, - "engines": { - "node": ">=v16" - }, - "peerDependencies": { - "@types/node": "*", - "cosmiconfig": ">=8.2", - "typescript": ">=4" - } - }, - "node_modules/cpu-features": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.10.tgz", - "integrity": "sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "dependencies": { - "buildcheck": "~0.0.6", - "nan": "^2.19.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", - "license": "Apache-2.0", - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/crc32-stream": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", - "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", - "dev": true, - "license": "MIT", - "dependencies": { - "crc-32": "^1.2.0", - "readable-stream": "^4.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/crc32-stream/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "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": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/crc32-stream/node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", - "dev": true, - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "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==", - "dev": true, - "license": "MIT" - }, - "node_modules/cron": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/cron/-/cron-3.2.1.tgz", - "integrity": "sha512-w2n5l49GMmmkBFEsH9FIDhjZ1n1QgTMOCMGuQtOXs5veNiosZmso6bQGuqOJSYAXXrG84WQFVneNk+Yt0Ua9iw==", - "license": "MIT", - "dependencies": { - "@types/luxon": "~3.4.0", - "luxon": "~3.5.0" - } - }, - "node_modules/cron-parser": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", - "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", - "license": "MIT", - "dependencies": { - "luxon": "^3.2.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/cross-env": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz", - "integrity": "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@epic-web/invariant": "^1.0.0", - "cross-spawn": "^7.0.6" - }, - "bin": { - "cross-env": "dist/bin/cross-env.js", - "cross-env-shell": "dist/bin/cross-env-shell.js" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/cross-fetch": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz", - "integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==", - "license": "MIT", - "dependencies": { - "node-fetch": "^2.7.0" - } - }, - "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/crypto-js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", - "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", - "license": "MIT" - }, - "node_modules/cssfilter": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz", - "integrity": "sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==", - "license": "MIT" - }, - "node_modules/csv-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/csv-parser/-/csv-parser-3.2.0.tgz", - "integrity": "sha512-fgKbp+AJbn1h2dcAHKIdKNSSjfp43BZZykXsCjzALjKy80VXQNHPFJ6T9Afwdzoj24aMkq8GwDS7KGcDPpejrA==", - "license": "MIT", - "bin": { - "csv-parser": "bin/csv-parser" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/dargs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", - "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/dayjs": { - "version": "1.11.19", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", - "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", - "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/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "license": "MIT", - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys/node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dedent": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz", - "integrity": "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==", - "license": "MIT", - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/deepmerge-ts": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", - "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/defu": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", - "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", - "dev": true, - "license": "MIT" - }, - "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/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.10" - } - }, - "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/destr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", - "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", - "dev": true, - "license": "MIT" - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "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": "5.2.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", - "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", - "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/dijkstrajs": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", - "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", - "license": "MIT" - }, - "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/docker-compose": { - "version": "0.24.8", - "resolved": "https://registry.npmjs.org/docker-compose/-/docker-compose-0.24.8.tgz", - "integrity": "sha512-plizRs/Vf15H+GCVxq2EUvyPK7ei9b/cVesHvjnX4xaXjM9spHe2Ytq0BitndFgvTJ3E3NljPNUEl7BAN43iZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "yaml": "^2.2.2" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/docker-modem": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-5.0.6.tgz", - "integrity": "sha512-ens7BiayssQz/uAxGzH8zGXCtiV24rRWXdjNha5V4zSOcxmAZsfGVm/PPFbwQdqEkDnhG+SyR9E3zSHUbOKXBQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "debug": "^4.1.1", - "readable-stream": "^3.5.0", - "split-ca": "^1.0.1", - "ssh2": "^1.15.0" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/dockerode": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/dockerode/-/dockerode-4.0.9.tgz", - "integrity": "sha512-iND4mcOWhPaCNh54WmK/KoSb35AFqPAUWFMffTQcp52uQt36b5uNwEJTSXntJZBbeGad72Crbi/hvDIv6us/6Q==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@balena/dockerignore": "^1.0.2", - "@grpc/grpc-js": "^1.11.1", - "@grpc/proto-loader": "^0.7.13", - "docker-modem": "^5.0.6", - "protobufjs": "^7.3.2", - "tar-fs": "^2.1.4", - "uuid": "^10.0.0" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/dockerode/node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true, - "license": "ISC" - }, - "node_modules/dockerode/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==", - "dev": true, - "license": "MIT", - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/dockerode/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==", - "dev": true, - "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/dockerode/node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", - "dev": true, - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "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/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/dotenv-expand": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", - "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } - }, - "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/effect": { - "version": "3.18.4", - "resolved": "https://registry.npmjs.org/effect/-/effect-3.18.4.tgz", - "integrity": "sha512-b1LXQJLe9D11wfnOKAk3PKxuqYshQ0Heez+y5pnkd3jLj1yx9QhM72zZ9uUrOQyNvrs2GZZd/3maL0ZV18YuDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.0.0", - "fast-check": "^3.23.1" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.267", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", - "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", - "dev": true, - "license": "ISC" - }, - "node_modules/elliptic": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", - "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", - "license": "MIT", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", - "license": "MIT" - }, - "node_modules/emitter-listener": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz", - "integrity": "sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ==", - "license": "BSD-2-Clause", - "dependencies": { - "shimmer": "^1.2.0" - } - }, - "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/empathic": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", - "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.18.4", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", - "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/enquirer": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", - "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", - "license": "MIT", - "dependencies": { - "ansi-colors": "^4.1.1", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "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/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/environment": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", - "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", - "dev": true, - "license": "MIT" - }, - "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-plugin-prettier": { - "version": "5.5.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz", - "integrity": "sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "prettier-linter-helpers": "^1.0.1", - "synckit": "^0.11.12" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", - "prettier": ">=3.0.0" - }, - "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { - "optional": true - } - } - }, - "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.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "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.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/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/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.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "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/ethers": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.16.0.tgz", - "integrity": "sha512-U1wulmetNymijEhpSEQ7Ct/P/Jw9/e7R1j5XIbPRydgV2DjLVMsULDlNksq3RQnFgKoLlZf88ijYtWEXcPa07A==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/ethers-io/" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@adraffy/ens-normalize": "1.10.1", - "@noble/curves": "1.2.0", - "@noble/hashes": "1.3.2", - "@types/node": "22.7.5", - "aes-js": "4.0.0-beta.5", - "tslib": "2.7.0", - "ws": "8.17.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/ethers/node_modules/@types/node": { - "version": "22.7.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", - "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.19.2" - } - }, - "node_modules/ethers/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", - "license": "0BSD" - }, - "node_modules/ethers/node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "license": "MIT" - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/eventemitter3": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", - "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", - "license": "MIT" - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/events-universal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", - "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "bare-events": "^2.7.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/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-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/exsolve": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.8.tgz", - "integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==", - "dev": true, - "license": "MIT" - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "license": "MIT" - }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "license": "MIT", - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/fast-check": { - "version": "3.23.2", - "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", - "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT", - "dependencies": { - "pure-rand": "^6.1.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "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-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/fast-fifo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", - "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-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==", - "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/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "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/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, - "node_modules/fflate": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", - "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", - "license": "MIT" - }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/figures/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "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-stream-rotator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/file-stream-rotator/-/file-stream-rotator-0.6.1.tgz", - "integrity": "sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ==", - "license": "MIT", - "dependencies": { - "moment": "^2.29.1" - } - }, - "node_modules/file-type": { - "version": "20.4.1", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-20.4.1.tgz", - "integrity": "sha512-hw9gNZXUfZ02Jo0uafWLaFVPter5/k2rfcrjFJJHX/77xtSDOfJuEFb6oKlFV86FLP1SuyHMW1PSk0U9M5tKkQ==", - "license": "MIT", - "dependencies": { - "@tokenizer/inflate": "^0.2.6", - "strtok3": "^10.2.0", - "token-types": "^6.0.0", - "uint8array-extras": "^1.4.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sindresorhus/file-type?sponsor=1" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "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": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "license": "BSD-3-Clause", - "bin": { - "flat": "cli.js" - } - }, - "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/flat-cache/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/flat-cache/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "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/flat-cache/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/flat-cache/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", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "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/fork-ts-checker-webpack-plugin": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", - "integrity": "sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.16.7", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cosmiconfig": "^8.2.0", - "deepmerge": "^4.2.2", - "fs-extra": "^10.0.0", - "memfs": "^3.4.1", - "minimatch": "^3.0.4", - "node-abort-controller": "^3.0.1", - "schema-utils": "^3.1.1", - "semver": "^7.3.5", - "tapable": "^2.2.1" - }, - "engines": { - "node": ">=12.13.0", - "yarn": ">=1.0.0" - }, - "peerDependencies": { - "typescript": ">3.6.0", - "webpack": "^5.11.0" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "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/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "license": "MIT", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "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/forwarded-parse": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.2.tgz", - "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==", - "license": "MIT" - }, - "node_modules/fp-ts": { - "version": "1.19.3", - "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz", - "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==", - "license": "MIT" - }, - "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==", - "dev": true, - "license": "MIT" - }, - "node_modules/fs-monkey": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.1.0.tgz", - "integrity": "sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw==", - "dev": true, - "license": "Unlicense" - }, - "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==", - "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/gaxios": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.3.tgz", - "integrity": "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==", - "license": "Apache-2.0", - "dependencies": { - "extend": "^3.0.2", - "https-proxy-agent": "^7.0.1", - "node-fetch": "^3.3.2", - "rimraf": "^5.0.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/gaxios/node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/gaxios/node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/gaxios/node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "license": "MIT", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, - "node_modules/gcp-metadata": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", - "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", - "license": "Apache-2.0", - "dependencies": { - "gaxios": "^7.0.0", - "google-logging-utils": "^1.0.0", - "json-bigint": "^1.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/generator-function": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", - "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/generic-pool": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", - "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "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-east-asian-width": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", - "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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-port": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", - "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/giget": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", - "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", + "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": { - "citty": "^0.1.6", - "consola": "^3.4.0", - "defu": "^6.1.4", - "node-fetch-native": "^1.6.6", - "nypm": "^0.6.0", - "pathe": "^2.0.3" + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" }, - "bin": { - "giget": "dist/cli.mjs" - } - }, - "node_modules/giget/node_modules/consola": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", - "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", - "dev": true, - "license": "MIT", "engines": { - "node": "^14.18.0 || >=16.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/git-raw-commits": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", - "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", + "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": { - "dargs": "^7.0.0", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "bin": { - "git-raw-commits": "cli.js" + "@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": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/git-raw-commits/node_modules/meow": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "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": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/git-raw-commits/node_modules/split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dev": true, - "license": "ISC", - "dependencies": { - "readable-stream": "^3.0.0" - } - }, - "node_modules/git-raw-commits/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/git-raw-commits/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "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/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/glob/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", + "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": { - "ini": "^1.3.4" + "@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": ">=4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "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": { - "type-fest": "^0.20.2" + "@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": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "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": { - "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" + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/google-logging-utils": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", - "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" + "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/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "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==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=6.0.0" } }, - "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==", - "license": "ISC" + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "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==", "dev": true, "license": "MIT" }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "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": { - "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" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/handlebars/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==", + "node_modules/@ljharb/through": { + "version": "2.3.14", + "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.14.tgz", + "integrity": "sha512-ajBvlKpWucBB17FuQYUShqpqy8GRgYEpJW0vWJbUu1CV9lWyrDCapy0lScU8T8Z6qn49sSwJB3+M+evYIdGg+A==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, + "node_modules/@lukeed/csprng": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", + "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/hardhat": { - "version": "2.28.6", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.28.6.tgz", - "integrity": "sha512-zQze7qe+8ltwHvhX5NQ8sN1N37WWZGw8L63y+2XcPxGwAjc/SMF829z3NS6o1krX0sryhAsVBK/xrwUqlsot4Q==", + "node_modules/@nestjs/cli": { + "version": "10.4.9", + "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.4.9.tgz", + "integrity": "sha512-s8qYd97bggqeK7Op3iD49X2MpFtW4LVNLAwXFkfbRxKME6IYT7X0muNTJ2+QfI8hpbNx9isWkrLWIp+g5FOhiA==", + "dev": true, "license": "MIT", "dependencies": { - "@ethereumjs/util": "^9.1.0", - "@ethersproject/abi": "^5.1.2", - "@nomicfoundation/edr": "0.12.0-next.23", - "@nomicfoundation/solidity-analyzer": "^0.1.0", - "@sentry/node": "^5.18.1", - "adm-zip": "^0.4.16", - "aggregate-error": "^3.0.0", - "ansi-escapes": "^4.3.0", - "boxen": "^5.1.2", - "chokidar": "^4.0.0", - "ci-info": "^2.0.0", - "debug": "^4.1.1", - "enquirer": "^2.3.0", - "env-paths": "^2.2.0", - "ethereum-cryptography": "^1.0.3", - "find-up": "^5.0.0", - "fp-ts": "1.19.3", - "fs-extra": "^7.0.1", - "immutable": "^4.0.0-rc.12", - "io-ts": "1.10.4", - "json-stream-stringify": "^3.1.4", - "keccak": "^3.0.2", - "lodash": "^4.17.11", - "micro-eth-signer": "^0.14.0", - "mnemonist": "^0.38.0", - "mocha": "^10.0.0", - "p-map": "^4.0.0", - "picocolors": "^1.1.0", - "raw-body": "^2.4.1", - "resolve": "1.17.0", - "semver": "^6.3.0", - "solc": "0.8.26", - "source-map-support": "^0.5.13", - "stacktrace-parser": "^0.1.10", - "tinyglobby": "^0.2.6", - "tsort": "0.0.1", - "undici": "^5.14.0", - "uuid": "^8.3.2", - "ws": "^7.4.6" + "@angular-devkit/core": "17.3.11", + "@angular-devkit/schematics": "17.3.11", + "@angular-devkit/schematics-cli": "17.3.11", + "@nestjs/schematics": "^10.0.1", + "chalk": "4.1.2", + "chokidar": "3.6.0", + "cli-table3": "0.6.5", + "commander": "4.1.1", + "fork-ts-checker-webpack-plugin": "9.0.2", + "glob": "10.4.5", + "inquirer": "8.2.6", + "node-emoji": "1.11.0", + "ora": "5.4.1", + "tree-kill": "1.2.2", + "tsconfig-paths": "4.2.0", + "tsconfig-paths-webpack-plugin": "4.2.0", + "typescript": "5.7.2", + "webpack": "5.97.1", + "webpack-node-externals": "3.0.0" }, "bin": { - "hardhat": "internal/cli/bootstrap.js" + "nest": "bin/nest.js" + }, + "engines": { + "node": ">= 16.14" }, "peerDependencies": { - "ts-node": "*", - "typescript": "*" + "@swc/cli": "^0.1.62 || ^0.3.0 || ^0.4.0 || ^0.5.0", + "@swc/core": "^1.3.62" }, "peerDependenciesMeta": { - "ts-node": { + "@swc/cli": { "optional": true }, - "typescript": { + "@swc/core": { "optional": true } } }, - "node_modules/hardhat/node_modules/@noble/hashes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", - "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT" - }, - "node_modules/hardhat/node_modules/@scure/base": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", - "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/hardhat/node_modules/@scure/bip32": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", - "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT", - "dependencies": { - "@noble/hashes": "~1.2.0", - "@noble/secp256k1": "~1.7.0", - "@scure/base": "~1.1.0" - } - }, - "node_modules/hardhat/node_modules/@scure/bip39": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", - "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT", - "dependencies": { - "@noble/hashes": "~1.2.0", - "@scure/base": "~1.1.0" - } - }, - "node_modules/hardhat/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" + "node_modules/@nestjs/cli/node_modules/typescript": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/hardhat/node_modules/ethereum-cryptography": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", - "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.2.0", - "@noble/secp256k1": "1.7.1", - "@scure/bip32": "1.1.5", - "@scure/bip39": "1.1.1" + "node": ">=14.17" } }, - "node_modules/hardhat/node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "node_modules/@nestjs/common": { + "version": "10.4.22", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.22.tgz", + "integrity": "sha512-fxJ4v85nDHaqT1PmfNCQ37b/jcv2OojtXTaK1P2uAXhzLf9qq6WNUOFvxBrV4fhQek1EQoT1o9oj5xAZmv3NRw==", "license": "MIT", "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "file-type": "20.4.1", + "iterare": "1.2.1", + "tslib": "2.8.1", + "uid": "2.0.2" }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/hardhat/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } } }, - "node_modules/hardhat/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "node_modules/@nestjs/config": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-3.3.0.tgz", + "integrity": "sha512-pdGTp8m9d0ZCrjTpjkUbZx6gyf2IKf+7zlkrPNMsJzYZ4bFRRTpXrnj+556/5uiI6AfL5mMrJc2u7dB6bvM+VA==", "license": "MIT", - "engines": { - "node": ">= 14.18.0" + "dependencies": { + "dotenv": "16.4.5", + "dotenv-expand": "10.0.0", + "lodash": "4.17.21" }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/hardhat/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" + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "rxjs": "^7.1.0" } }, - "node_modules/hardhat/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "license": "MIT", + "node_modules/@nestjs/config/node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "license": "BSD-2-Clause", "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/hardhat/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" } }, - "node_modules/hardhat/node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "node_modules/@nestjs/core": { + "version": "10.4.22", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.22.tgz", + "integrity": "sha512-6IX9+VwjiKtCjx+mXVPncpkQ5ZjKfmssOZPFexmT+6T9H9wZ3svpYACAo7+9e7Nr9DZSoRZw3pffkJP7Z0UjaA==", + "hasInstallScript": true, "license": "MIT", - "engines": { - "node": ">=8.3.0" + "dependencies": { + "@nuxtjs/opencollective": "0.3.2", + "fast-safe-stringify": "2.1.1", + "iterare": "1.2.1", + "path-to-regexp": "3.3.0", + "tslib": "2.8.1", + "uid": "2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" }, "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "@nestjs/common": "^10.0.0", + "@nestjs/microservices": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "@nestjs/websockets": "^10.0.0", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" }, "peerDependenciesMeta": { - "bufferutil": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { "optional": true }, - "utf-8-validate": { + "@nestjs/websockets": { "optional": true } } }, - "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==", + "node_modules/@nestjs/platform-express": { + "version": "10.4.22", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.22.tgz", + "integrity": "sha512-ySSq7Py/DFozzZdNDH67m/vHoeVdphDniWBnl6q5QVoXldDdrZIHLXLRMPayTDh5A95nt7jjJzmD4qpTbNQ6tA==", "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "body-parser": "1.20.4", + "cors": "2.8.5", + "express": "4.22.1", + "multer": "2.0.2", + "tslib": "2.8.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0" } }, - "node_modules/has-own-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", - "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==", - "dev": true, + "node_modules/@nestjs/platform-express/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, "engines": { - "node": ">=8" + "node": ">= 0.6" } }, - "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==", + "node_modules/@nestjs/platform-express/node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0" + "safe-buffer": "5.2.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.6" } }, - "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==", + "node_modules/@nestjs/platform-express/node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, + "node_modules/@nestjs/platform-express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "ms": "2.0.0" } }, - "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==", + "node_modules/@nestjs/platform-express/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/@nestjs/platform-express/node_modules/express": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", "license": "MIT", "dependencies": { - "has-symbols": "^1.0.3" + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.14.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" }, "engines": { - "node": ">= 0.4" + "node": ">= 0.10.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/hashery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.0.tgz", - "integrity": "sha512-nhQ6ExaOIqti2FDWoEMWARUqIKyjr2VcZzXShrI+A3zpeiuPWzx6iPftt44LhP74E5sW36B75N6VHbvRtpvO6Q==", + "node_modules/@nestjs/platform-express/node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", "license": "MIT", "dependencies": { - "hookified": "^1.14.0" + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" }, "engines": { - "node": ">=20" + "node": ">= 0.8" } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "node_modules/@nestjs/platform-express/node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, "engines": { - "node": ">= 0.4" + "node": ">= 0.6" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "node_modules/@nestjs/platform-express/node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", "license": "MIT", - "bin": { - "he": "bin/he" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/helmet": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.2.0.tgz", - "integrity": "sha512-ZRiwvN089JfMXokizgqEPXsl2Guk094yExfoDXR0cBYWxtBbaSww/w+vT4WEJsBW2iTUi1GgZ6swmoug3Oy4Xw==", + "node_modules/@nestjs/platform-express/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "license": "MIT", + "bin": { + "mime": "cli.js" + }, "engines": { - "node": ">=16.0.0" + "node": ">=4" } }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "node_modules/@nestjs/platform-express/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "license": "MIT", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" + "engines": { + "node": ">= 0.6" } }, - "node_modules/hookified": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz", - "integrity": "sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==", + "node_modules/@nestjs/platform-express/node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "license": "MIT" }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "license": "ISC", + "node_modules/@nestjs/platform-express/node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", "dependencies": { - "lru-cache": "^6.0.0" + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" }, "engines": { - "node": ">=10" + "node": ">= 0.8.0" } }, - "node_modules/hosted-git-info/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==", - "dev": true, - "license": "ISC", + "node_modules/@nestjs/platform-express/node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" }, "engines": { - "node": ">=10" + "node": ">= 0.8.0" } }, - "node_modules/hosted-git-info/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/@nestjs/schematics": { + "version": "10.2.3", + "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-10.2.3.tgz", + "integrity": "sha512-4e8gxaCk7DhBxVUly2PjYL4xC2ifDFexCqq1/u4TtivLGXotVk0wHdYuPYe1tHTHuR1lsOkRbfOCpkdTnigLVg==", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "17.3.11", + "@angular-devkit/schematics": "17.3.11", + "comment-json": "4.2.5", + "jsonc-parser": "3.3.1", + "pluralize": "8.0.0" + }, + "peerDependencies": { + "typescript": ">=4.8.2" + } }, - "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==", + "node_modules/@nestjs/schematics/node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", "dev": true, "license": "MIT" }, - "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==", + "node_modules/@nestjs/testing": { + "version": "10.4.22", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.22.tgz", + "integrity": "sha512-HO9aPus3bAedAC+jKVAA8jTdaj4fs5M9fing4giHrcYV2txe9CvC1l1WAjwQ9RDhEHdugjY4y+FZA/U/YqPZrA==", + "dev": true, "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" + "tslib": "2.8.1" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/microservices": "^10.0.0", + "@nestjs/platform-express": "^10.0.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + } } }, - "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==", + "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": { - "agent-base": "6", - "debug": "4" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">= 6" + "node": ">= 8" } }, - "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==", + "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": "Apache-2.0", + "license": "MIT", "engines": { - "node": ">=10.17.0" + "node": ">= 8" } }, - "node_modules/husky": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", - "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "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", - "bin": { - "husky": "lib/bin.js" + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" + "node": ">= 8" } }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/@nuxtjs/opencollective": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", + "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "chalk": "^4.1.0", + "consola": "^2.15.0", + "node-fetch": "^2.6.1" + }, + "bin": { + "opencollective": "bin/opencollective.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=8.0.0", + "npm": ">=5.0.0" } }, - "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==", + "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==", "dev": true, "license": "MIT", + "optional": true, "engines": { - "node": ">= 4" + "node": ">=14" } }, - "node_modules/immutable": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", - "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", - "license": "MIT" - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", "dev": true, "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, "engines": { - "node": ">=6" + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/pkgr" } }, - "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", + "node_modules/@prisma/client": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.19.2.tgz", + "integrity": "sha512-gR2EMvfK/aTxsuooaDA32D8v+us/8AAet+C3J1cc04SW35FPdZYgLF+iN4NDLUgAaUGTKdAB0CYenu1TAgGdMg==", + "hasInstallScript": true, + "license": "Apache-2.0", "engines": { - "node": ">=4" + "node": ">=18.18" + }, + "peerDependencies": { + "prisma": "*", + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + }, + "typescript": { + "optional": true + } } }, - "node_modules/import-in-the-middle": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-2.0.6.tgz", - "integrity": "sha512-3vZV3jX0XRFW3EJDTwzWoZa+RH1b8eTTx6YOCjglrLyPuepwoBti1k3L2dKwdCUrnVEfc5CuRuGstaC/uQJJaw==", + "node_modules/@prisma/config": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.19.2.tgz", + "integrity": "sha512-kadBGDl+aUswv/zZMk9Mx0C8UZs1kjao8H9/JpI4Wh4SHZaM7zkTwiKn/iFLfRg+XtOAo/Z/c6pAYhijKl0nzQ==", + "devOptional": true, "license": "Apache-2.0", "dependencies": { - "acorn": "^8.15.0", - "acorn-import-attributes": "^1.9.5", - "cjs-module-lexer": "^2.2.0", - "module-details-from-path": "^1.0.4" + "c12": "3.1.0", + "deepmerge-ts": "7.1.5", + "effect": "3.18.4", + "empathic": "2.0.0" } }, - "node_modules/import-in-the-middle/node_modules/cjs-module-lexer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz", - "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==", - "license": "MIT" + "node_modules/@prisma/debug": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.19.2.tgz", + "integrity": "sha512-lFnEZsLdFLmEVCVNdskLDCL8Uup41GDfU0LUfquw+ercJC8ODTuL0WNKgOKmYxCJVvFwf0OuZBzW99DuWmoH2A==", + "devOptional": true, + "license": "Apache-2.0" }, - "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", + "node_modules/@prisma/engines": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.19.2.tgz", + "integrity": "sha512-TTkJ8r+uk/uqczX40wb+ODG0E0icVsMgwCTyTHXehaEfb0uo80M9g1aW1tEJrxmFHeOZFXdI2sTA1j1AgcHi4A==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", "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" + "@prisma/debug": "6.19.2", + "@prisma/engines-version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", + "@prisma/fetch-engine": "6.19.2", + "@prisma/get-platform": "6.19.2" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } + "node_modules/@prisma/engines-version": { + "version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7.tgz", + "integrity": "sha512-03bgb1VD5gvuumNf+7fVGBzfpJPjmqV423l/WxsWk2cNQ42JD0/SsFBPhN6z8iAvdHs07/7ei77SKu7aZfq8bA==", + "devOptional": true, + "license": "Apache-2.0" }, - "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", - "engines": { - "node": ">=8" + "node_modules/@prisma/fetch-engine": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.19.2.tgz", + "integrity": "sha512-h4Ff4Pho+SR1S8XerMCC12X//oY2bG3Iug/fUnudfcXEUnIeRiBdXHFdGlGOgQ3HqKgosTEhkZMvGM9tWtYC+Q==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.19.2", + "@prisma/engines-version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", + "@prisma/get-platform": "6.19.2" } }, - "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", + "node_modules/@prisma/get-platform": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.19.2.tgz", + "integrity": "sha512-PGLr06JUSTqIvztJtAzIxOwtWKtJm5WwOG6xpsgD37Rc84FpfUBGLKz65YpJBGtkRQGXTYEFie7pYALocC3MtA==", + "devOptional": true, + "license": "Apache-2.0", "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "@prisma/debug": "6.19.2" } }, - "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": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/inquirer": { - "version": "8.2.6", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", - "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", + "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": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.5.5", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6", - "wrap-ansi": "^6.0.1" - }, - "engines": { - "node": ">=12.0.0" + "type-detect": "4.0.8" } }, - "node_modules/inquirer/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "node_modules/@sinonjs/commons/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", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/io-ts": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz", - "integrity": "sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==", - "license": "MIT", + "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": { - "fp-ts": "^1.0.0" + "@sinonjs/commons": "^3.0.0" } }, - "node_modules/ioredis": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.9.2.tgz", - "integrity": "sha512-tAAg/72/VxOUW7RQSX1pIxJVucYKcjFjfvj60L57jrZpYCHC3XN0WCQ3sNYL4Gmvv+7GPvTAjc+KSdeNuE8oWQ==", + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@tokenizer/inflate": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.2.7.tgz", + "integrity": "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==", "license": "MIT", "dependencies": { - "@ioredis/commands": "1.5.0", - "cluster-key-slot": "^1.1.0", - "debug": "^4.3.4", - "denque": "^2.1.0", - "lodash.defaults": "^4.2.0", - "lodash.isarguments": "^3.1.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0", - "standard-as-callback": "^2.1.0" + "debug": "^4.4.0", + "fflate": "^0.8.2", + "token-types": "^6.0.0" }, "engines": { - "node": ">=12.22.0" + "node": ">=18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ioredis" + "type": "github", + "url": "https://github.com/sponsors/Borewit" } }, - "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/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "license": "MIT" }, - "node_modules/is-arguments": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", - "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "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==", + "dev": true, + "license": "MIT" }, - "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==", + "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==", "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==", - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } + "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==", + "dev": true, + "license": "MIT" }, - "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/@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==", + "dev": true, + "license": "MIT" }, - "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==", + "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": { - "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==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" } }, - "node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "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", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "@babel/types": "^7.0.0" } }, - "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==", + "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", - "engines": { - "node": ">=6" + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" } }, - "node_modules/is-generator-function": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", - "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "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": { - "call-bound": "^1.0.4", - "generator-function": "^2.0.0", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@babel/types": "^7.28.2" } }, - "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==", - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" + "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/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "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", - "engines": { - "node": ">=8" + "dependencies": { + "@types/connect": "*", + "@types/node": "*" } }, - "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==", + "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", - "engines": { - "node": ">=0.12.0" + "dependencies": { + "@types/node": "*" } }, - "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==", + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" } }, - "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==", + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" } }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", + "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "^1" } }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "node_modules/@types/express-serve-static-core": { + "version": "4.19.8", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", + "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", + "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" } }, - "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==", + "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", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "@types/node": "*" } }, - "node_modules/is-text-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", - "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", + "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": { - "text-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" + "@types/istanbul-lib-coverage": "*" } }, - "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==", + "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": { - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@types/istanbul-lib-report": "*" } }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "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", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" } }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "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/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC" - }, - "node_modules/isomorphic-ws": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", - "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "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", - "peerDependencies": { - "ws": "*" + "dependencies": { + "@types/ms": "*", + "@types/node": "*" } }, - "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==", + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "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==", + "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": "BSD-3-Clause", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", + "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "dev": true, + "license": "MIT", "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" + "undici-types": "~6.21.0" } }, - "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==", + "node_modules/@types/passport": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz", + "integrity": "sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "@types/express": "*" } }, - "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==", + "node_modules/@types/passport-jwt": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-3.0.13.tgz", + "integrity": "sha512-fjHaC6Bv8EpMMqzTnHP32SXlZGaNfBPC/Po5dmRGYi2Ky7ljXPbGnOy+SxZqa6iZvFgVhoJ1915Re3m93zmcfA==", "dev": true, "license": "MIT", "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@types/express": "*", + "@types/jsonwebtoken": "*", + "@types/passport-strategy": "*" } }, - "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==", + "node_modules/@types/passport-strategy": { + "version": "0.2.38", + "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz", + "integrity": "sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" + "@types/express": "*", + "@types/passport": "*" } }, - "node_modules/istanbul-lib-source-maps/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==", + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, - "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==", + "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": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/iterare": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", - "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==", - "license": "ISC", - "engines": { - "node": ">=6" - } + "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/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", + "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": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "@types/node": "*" } }, - "node_modules/jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "node_modules/@types/serve-static": { + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", "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 - } + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "<1" } }, - "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==", + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", "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" + "@types/mime": "^1", + "@types/node": "*" } }, - "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==", + "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/validator": { + "version": "13.15.10", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.10.tgz", + "integrity": "sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==", + "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": { - "@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" + "@types/yargs-parser": "*" } }, - "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==", + "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": { - "@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" + "@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": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { - "node-notifier": { + "typescript": { "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==", + "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": "MIT", + "license": "BSD-2-Clause", "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" + "@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": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" + "eslint": "^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { + "typescript": { "optional": true } } }, - "node_modules/jest-config/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/jest-config/node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "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, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-config/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "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" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { - "node": "*" + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/jest-config/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "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": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "@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": "*" + "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/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "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", - "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": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "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==", + "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": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "detect-newline": "^3.0.0" + "@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": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "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==", + "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": { - "@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" + "@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": "^14.15.0 || ^16.10.0 || >=18.0.0" + "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/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==", + "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": { - "@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" + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "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==", + "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": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "license": "ISC" }, - "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==", + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", "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" + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, - "node_modules/jest-junit": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-16.0.0.tgz", - "integrity": "sha512-A94mmw6NfJab4Fg/BlvVOUXzXgF0XIH6EmTgJ5NDPp4xoKq0Kr7sErb+4Xs9nZvu58pJojz5RFGpqnZYJTrRfQ==", + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "mkdirp": "^1.0.4", - "strip-ansi": "^6.0.1", - "uuid": "^8.3.2", - "xml": "^1.0.1" - }, - "engines": { - "node": ">=10.12.0" - } + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "dev": true, + "license": "MIT" }, - "node_modules/jest-junit/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", "dev": true, "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" } }, - "node_modules/jest-junit/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", "dev": true, - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } + "license": "MIT" }, - "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==", + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", "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" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" } }, - "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==", + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", "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" + "@xtuc/ieee754": "^1.2.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==", + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "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" + "@xtuc/long": "4.2.2" } }, - "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==", + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", "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" - } + "license": "MIT" }, - "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==", + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" } }, - "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==", + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", "dev": true, "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, - "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==", + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", "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" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" } }, - "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==", + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", "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" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, - "node_modules/jest-resolve/node_modules/resolve": { - "version": "1.22.11", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", "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" + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" } }, - "node_modules/jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "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" + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.4.0" } }, - "node_modules/jest-runner/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==", + "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": "BSD-3-Clause", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=0.4.0" } }, - "node_modules/jest-runner/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==", + "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": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "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/jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "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" + "ajv": "^8.0.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } } }, - "node_modules/jest-runtime/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" } }, - "node_modules/jest-runtime/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, - "license": "ISC", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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": { - "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" + "type-fest": "^0.21.3" }, "engines": { - "node": "*" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-runtime/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "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": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": "*" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "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==", "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": ">=8" } }, - "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, + "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": { - "@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" + "color-convert": "^2.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-util/node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "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, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, "engines": { - "node": ">=8" + "node": ">= 8" } }, - "node_modules/jest-util/node_modules/picomatch": { + "node_modules/anymatch/node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", @@ -13504,5673 +3221,5349 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "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==", + "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/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": 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-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/array-timsort": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", + "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", + "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", - "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": ">=8" } }, - "node_modules/jest-watcher": { + "node_modules/babel-jest": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "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/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", + "@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", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" + "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/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==", + "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": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "@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": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "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==", + "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": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "has-flag": "^4.0.0" + "@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": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=8" } }, - "node_modules/jiti": { - "version": "1.21.7", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", - "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "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": "MIT", + "license": "ISC", "bin": { - "jiti": "bin/jiti.js" - } - }, - "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" + "semver": "bin/semver.js" } }, - "node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", - "license": "MIT" - }, - "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==", + "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" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "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" + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" }, "engines": { - "node": ">=6" - } - }, - "node_modules/json-bigint": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", - "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", - "license": "MIT", - "dependencies": { - "bignumber.js": "^9.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "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" - }, - "node_modules/json-stream-stringify": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/json-stream-stringify/-/json-stream-stringify-3.1.6.tgz", - "integrity": "sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog==", "license": "MIT", - "engines": { - "node": ">=7.10.1" + "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/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "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", - "bin": { - "json5": "lib/cli.js" + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { - "node": ">=6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/jsonc-parser": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", - "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", + "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==", "dev": true, "license": "MIT" }, - "node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "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==", "dev": true, - "engines": [ - "node >= 0.2.0" + "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/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "node_modules/baseline-browser-mapping": { + "version": "2.9.16", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.16.tgz", + "integrity": "sha512-KeUZdBuxngy825i8xvzaK1Ncnkx0tBmb3k8DkEuqjKRkmtvNTjey2ZsNeh8Dw4lfKvbCOu9oeNx2TKm2vHqcRw==", "dev": true, - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, + "license": "Apache-2.0", "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" + "baseline-browser-mapping": "dist/cli.js" } }, - "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==", + "node_modules/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==", + "hasInstallScript": true, "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" + "node-addon-api": "^8.3.0", + "node-gyp-build": "^4.8.4" }, "engines": { - "node": ">=12", - "npm": ">=6" + "node": ">= 18" } }, - "node_modules/jwa": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", - "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "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", - "dependencies": { - "buffer-equal-constant-time": "^1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, "license": "MIT", "dependencies": { - "jwa": "^2.0.1", - "safe-buffer": "^5.0.1" + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" } }, - "node_modules/keccak": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", - "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", - "hasInstallScript": true, + "node_modules/body-parser": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", "license": "MIT", "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0", - "readable-stream": "^3.6.0" + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" }, "engines": { - "node": ">=10.0.0" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/keccak/node_modules/node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", - "license": "MIT" - }, - "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, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { - "json-buffer": "3.0.1" + "ms": "2.0.0" } }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "balanced-match": "^1.0.0" } }, - "node_modules/kleur": { + "node_modules/braces": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "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": ">=6" + "node": ">=8" } }, - "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/lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "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": { - "readable-stream": "^2.0.5" + "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": ">= 0.6.3" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/lazystream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lazystream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "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": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/lazystream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/lazystream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "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": "MIT", + "license": "Apache-2.0", "dependencies": { - "safe-buffer": "~5.1.0" + "node-int64": "^0.4.0" } }, - "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==", + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "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", - "engines": { - "node": ">=6" + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, - "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", + "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": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "streamsearch": "^1.1.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=10.16.0" } }, - "node_modules/libphonenumber-js": { - "version": "1.12.34", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.34.tgz", - "integrity": "sha512-v/Ip8k8eYdp7bINpzqDh46V/PaQ8sK+qi97nMQgjZzFlb166YFqlR/HVI+MzsI9JqcyyVWCOipmmretiaSyQyw==", - "license": "MIT" - }, - "node_modules/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "dev": true, + "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": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" + "node": ">= 0.8" } }, - "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/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", - "dev": true, + "node_modules/c12": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", + "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", + "devOptional": true, "license": "MIT", "dependencies": { - "uc.micro": "^2.0.0" + "chokidar": "^4.0.3", + "confbox": "^0.2.2", + "defu": "^6.1.4", + "dotenv": "^16.6.1", + "exsolve": "^1.0.7", + "giget": "^2.0.0", + "jiti": "^2.4.2", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "perfect-debounce": "^1.0.0", + "pkg-types": "^2.2.0", + "rc9": "^2.1.2" + }, + "peerDependencies": { + "magicast": "^0.3.5" + }, + "peerDependenciesMeta": { + "magicast": { + "optional": true + } } }, - "node_modules/lint-staged": { - "version": "15.5.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.5.2.tgz", - "integrity": "sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==", - "dev": true, + "node_modules/c12/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "devOptional": true, "license": "MIT", "dependencies": { - "chalk": "^5.4.1", - "commander": "^13.1.0", - "debug": "^4.4.0", - "execa": "^8.0.1", - "lilconfig": "^3.1.3", - "listr2": "^8.2.5", - "micromatch": "^4.0.8", - "pidtree": "^0.6.0", - "string-argv": "^0.3.2", - "yaml": "^2.7.0" - }, - "bin": { - "lint-staged": "bin/lint-staged.js" + "readdirp": "^4.0.1" }, "engines": { - "node": ">=18.12.0" + "node": ">= 14.16.0" }, "funding": { - "url": "https://opencollective.com/lint-staged" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/lint-staged/node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "dev": true, + "node_modules/c12/node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "devOptional": true, "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "bin": { + "jiti": "lib/jiti-cli.mjs" } }, - "node_modules/lint-staged/node_modules/commander": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", - "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", - "dev": true, + "node_modules/c12/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "devOptional": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, - "node_modules/lint-staged/node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" + "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": ">=16.17" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lint-staged/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, + "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", - "engines": { - "node": ">=16" + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "license": "Apache-2.0", "engines": { - "node": ">=16.17.0" + "node": ">= 0.4" } }, - "node_modules/lint-staged/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, + "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": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lint-staged/node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "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": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/lint-staged/node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "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", - "dependencies": { - "path-key": "^4.0.0" - }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "node_modules/caniuse-lite": { + "version": "1.0.30001765", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001765.tgz", + "integrity": "sha512-LWcNtSyZrakjECqmpP4qdg0MMGdN368D7X8XvvAqOcqMv0RxnlqVKZl2V6/mBR68oYMxOZPLw/gO7DuisMHUvQ==", "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==", "license": "MIT", "dependencies": { - "mimic-fn": "^4.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/lint-staged/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "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": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10" } }, - "node_modules/lint-staged/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==", + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "license": "MIT" }, - "node_modules/lint-staged/node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "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": ">=12" + "node": ">= 8.10.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/listr2": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz", - "integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==", + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", "dev": true, "license": "MIT", - "dependencies": { - "cli-truncate": "^4.0.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", - "log-update": "^6.1.0", - "rfdc": "^1.4.1", - "wrap-ansi": "^9.0.0" - }, "engines": { - "node": ">=18.0.0" + "node": ">=6.0" } }, - "node_modules/listr2/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "devOptional": true, "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "dependencies": { + "consola": "^3.2.3" } }, - "node_modules/listr2/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==", - "dev": true, + "node_modules/citty/node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "devOptional": true, "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": "^14.18.0 || >=16.10.0" } }, - "node_modules/listr2/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "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/listr2/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "node_modules/class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==", + "license": "MIT" + }, + "node_modules/class-validator": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.3.tgz", + "integrity": "sha512-rXXekcjofVN1LTOSw+u4u9WXVEUvNBVjORW154q/IdmYWy1nMbOU9aNtZB0t8m+FJQ9q91jlr2f9CwwUFdFMRA==", + "license": "MIT", + "dependencies": { + "@types/validator": "^13.15.3", + "libphonenumber-js": "^1.11.1", + "validator": "^13.15.20" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" + "restore-cursor": "^3.1.0" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/listr2/node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, "engines": { - "node": ">=12" + "node": ">=6" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/listr2/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" + "string-width": "^4.2.0" }, "engines": { - "node": ">=18" + "node": "10.* || >= 12.*" }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "optionalDependencies": { + "@colors/colors": "1.5.0" } }, - "node_modules/loader-runner": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", "dev": true, - "license": "MIT", + "license": "ISC", "engines": { - "node": ">=6.11.5" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">= 10" } }, - "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==", - "license": "MIT", + "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==", + "dev": true, + "license": "ISC", "dependencies": { - "p-locate": "^5.0.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", - "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.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", - "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.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", - "dev": true, - "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.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "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==", + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true, - "license": "MIT" - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.8" } }, - "node_modules/log-update": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", - "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "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", - "dependencies": { - "ansi-escapes": "^7.0.0", - "cli-cursor": "^5.0.0", - "slice-ansi": "^7.1.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" } }, - "node_modules/log-update/node_modules/ansi-escapes": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.2.0.tgz", - "integrity": "sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==", + "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-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": { - "environment": "^1.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=7.0.0" } }, - "node_modules/log-update/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } + "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/log-update/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==", + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "dev": true, "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">= 6" } }, - "node_modules/log-update/node_modules/cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "node_modules/comment-json": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.5.tgz", + "integrity": "sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==", "dev": true, "license": "MIT", "dependencies": { - "restore-cursor": "^5.0.0" + "array-timsort": "^1.0.3", + "core-util-is": "^1.0.3", + "esprima": "^4.0.1", + "has-own-prop": "^2.0.0", + "repeat-string": "^1.6.1" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 6" } }, - "node_modules/log-update/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, "license": "MIT" }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", - "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", - "dev": true, + "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": { - "get-east-asian-width": "^1.3.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" } }, - "node_modules/log-update/node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", - "dev": true, + "node_modules/confbox": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.4.tgz", + "integrity": "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", + "license": "MIT" + }, + "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", - "dependencies": { - "mimic-function": "^5.0.0" - }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.6" } }, - "node_modules/log-update/node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "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", - "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" - }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.6" } }, - "node_modules/log-update/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==", + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "license": "MIT" }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", - "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", - "dev": true, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", "license": "MIT", "dependencies": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" + "object-assign": "^4", + "vary": "^1" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "node": ">= 0.10" } }, - "node_modules/log-update/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" }, "engines": { - "node": ">=18" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/log-update/node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "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": { - "ansi-regex": "^6.0.1" + "@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" }, - "engines": { - "node": ">=12" + "bin": { + "create-jest": "bin/create-jest.js" }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "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==", + "dev": 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==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">= 8" } }, - "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==", + "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": { - "@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" + "ms": "^2.1.3" }, "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/logform/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": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "license": "Apache-2.0" - }, - "node_modules/lru_map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", - "license": "MIT" - }, - "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==", + "node_modules/dedent": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz", + "integrity": "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==", "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } } }, - "node_modules/lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "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/luxon": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz", - "integrity": "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==", + "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==", + "dev": true, "license": "MIT", "engines": { - "node": ">=12" + "node": ">=0.10.0" } }, - "node_modules/magic-string": { - "version": "0.30.8", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", - "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - }, + "node_modules/deepmerge-ts": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", + "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", + "devOptional": true, + "license": "BSD-3-Clause", "engines": { - "node": ">=12" + "node": ">=16.0.0" } }, - "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==", - "dev": true, - "license": "ISC" - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "tmpl": "1.0.5" + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "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==", "dev": true, "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/map-or-similar": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", - "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "devOptional": true, "license": "MIT" }, - "node_modules/mapped-types": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/mapped-types/-/mapped-types-0.0.1.tgz", - "integrity": "sha512-9WtZd+/WCFNmkLJh5LdEFQq4QJJ60E+H86Xus35D5DjyuD6O15F9OFOaGLkBJscJWh91WIzYv1OWZhrHslm3fg==", + "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": ">= 4" + "node": ">= 0.8" } }, - "node_modules/markdown-it": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", - "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", - "dev": true, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "license": "MIT", - "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "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==", + "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": ">= 0.4" + "node": ">=8" } }, - "node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "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" - }, - "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": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "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": "Unlicense", + "license": "MIT", "dependencies": { - "fs-monkey": "^1.0.4" + "path-type": "^4.0.0" }, "engines": { - "node": ">= 4.0.0" + "node": ">=8" } }, - "node_modules/memoizerific": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", - "integrity": "sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==", - "license": "MIT", + "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": { - "map-or-similar": "^1.5.0" - } - }, - "node_modules/memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "esutils": "^2.0.2" + }, "engines": { - "node": ">= 0.10.0" + "node": ">=6.0.0" } }, - "node_modules/meow": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", - "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", - "dev": true, - "license": "MIT", + "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": ">=16.10" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://dotenvx.com" } }, - "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", + "node_modules/dotenv-expand": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", + "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", + "license": "BSD-2-Clause", "engines": { - "node": ">= 8" + "node": ">=12" } }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "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.6" + "node": ">= 0.4" } }, - "node_modules/micro-eth-signer": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/micro-eth-signer/-/micro-eth-signer-0.14.0.tgz", - "integrity": "sha512-5PLLzHiVYPWClEvZIXXFu5yutzpadb73rnQCpUqIHu3No3coFuWQNfE5tkBQJ7djuLYl6aRLaS0MgWJYGoqiBw==", - "license": "MIT", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "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": { - "@noble/curves": "~1.8.1", - "@noble/hashes": "~1.7.1", - "micro-packed": "~0.7.2" + "safe-buffer": "^5.0.1" } }, - "node_modules/micro-eth-signer/node_modules/@noble/curves": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.2.tgz", - "integrity": "sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g==", + "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/effect": { + "version": "3.18.4", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.18.4.tgz", + "integrity": "sha512-b1LXQJLe9D11wfnOKAk3PKxuqYshQ0Heez+y5pnkd3jLj1yx9QhM72zZ9uUrOQyNvrs2GZZd/3maL0ZV18YuDA==", + "devOptional": true, "license": "MIT", "dependencies": { - "@noble/hashes": "1.7.2" - }, - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "@standard-schema/spec": "^1.0.0", + "fast-check": "^3.23.1" } }, - "node_modules/micro-eth-signer/node_modules/@noble/hashes": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.2.tgz", - "integrity": "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ==", + "node_modules/electron-to-chromium": { + "version": "1.5.267", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", + "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", + "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": "^14.21.3 || >=16" + "node": ">=12" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, - "node_modules/micro-packed": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/micro-packed/-/micro-packed-0.7.3.tgz", - "integrity": "sha512-2Milxs+WNC00TRlem41oRswvw31146GiSaoCT7s3Xi2gMUglW5QBeqlQaZeHr5tJx9nm3i57LNXPqxOOaWtTYg==", + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/empathic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "devOptional": true, "license": "MIT", - "dependencies": { - "@scure/base": "~1.2.5" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": ">=14" } }, - "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, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, "engines": { - "node": ">=8.6" + "node": ">= 0.8" } }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/enhanced-resolve": { + "version": "5.18.4", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", + "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8.6" + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "engines": { + "node": ">=10.13.0" } }, - "node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "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", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" + "dependencies": { + "is-arrayish": "^0.2.1" } }, - "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==", + "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.6" + "node": ">= 0.4" } }, - "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" - }, + "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.6" + "node": ">= 0.4" } }, - "node_modules/mime-types/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==", + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "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.6" + "node": ">= 0.4" } }, - "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==", + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "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==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "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", - "engines": { - "node": ">=4" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "license": "ISC" - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", - "license": "MIT" - }, - "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" + "@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": ">=16 || 14 >=14.17" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://opencollective.com/eslint" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "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", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" } }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "node_modules/eslint-plugin-prettier": { + "version": "5.5.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz", + "integrity": "sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==", "dev": true, "license": "MIT", "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" + "prettier-linter-helpers": "^1.0.1", + "synckit": "^0.11.12" }, "engines": { - "node": ">= 6" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } } }, - "node_modules/minimist-options/node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "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": "MIT", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", + "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": ">=16 || 14 >=14.17" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "license": "MIT", "dependencies": { - "minimist": "^1.2.6" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "bin": { - "mkdirp": "bin/cmd.js" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "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==", + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, - "license": "MIT" - }, - "node_modules/mnemonist": { - "version": "0.38.5", - "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz", - "integrity": "sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==", "license": "MIT", "dependencies": { - "obliterator": "^2.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/mocha": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", - "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", - "license": "MIT", + "node_modules/eslint/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": { - "ansi-colors": "^4.1.3", - "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", - "debug": "^4.3.5", - "diff": "^5.2.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^8.1.0", - "he": "^1.2.0", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", - "ms": "^2.1.3", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", - "yargs-unparser": "^2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 14.0.0" + "node": ">=10.13.0" } }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "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.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "license": "ISC", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "node_modules/mocha/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "license": "ISC", + "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": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": ">=12" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://opencollective.com/eslint" } }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" + "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": ">=10" + "node": ">=4" } }, - "node_modules/mocha/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==", - "license": "MIT", + "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": { - "has-flag": "^4.0.0" + "estraverse": "^5.1.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=0.10" } }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "license": "MIT", + "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": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=10" + "node": ">=4.0" } }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "license": "ISC", + "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": ">=10" + "node": ">=4.0" } }, - "node_modules/module-details-from-path": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", - "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", - "license": "MIT" - }, - "node_modules/moment": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", - "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", - "license": "MIT", + "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": "*" + "node": ">=0.10.0" } }, - "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/msgpackr": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.8.tgz", - "integrity": "sha512-bC4UGzHhVvgDNS7kn9tV8fAucIYUBuGojcaLiz7v+P63Lmtm0Xeji8B/8tYKddALXxJLpwIeBmUN3u64C4YkRA==", + "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", - "optionalDependencies": { - "msgpackr-extract": "^3.0.2" + "engines": { + "node": ">= 0.6" } }, - "node_modules/msgpackr-extract": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", - "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", - "hasInstallScript": true, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, "license": "MIT", - "optional": true, - "dependencies": { - "node-gyp-build-optional-packages": "5.2.2" - }, - "bin": { - "download-msgpackr-prebuilds": "bin/download-prebuilds.js" - }, - "optionalDependencies": { - "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", - "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" + "engines": { + "node": ">=0.8.x" } }, - "node_modules/multer": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz", - "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", + "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": { - "append-field": "^1.0.0", - "busboy": "^1.6.0", - "concat-stream": "^2.0.0", - "mkdirp": "^0.5.6", - "object-assign": "^4.1.1", - "type-is": "^1.6.18", - "xtend": "^4.0.2" + "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.16.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true, - "license": "ISC" - }, - "node_modules/nan": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.24.0.tgz", - "integrity": "sha512-Vpf9qnVW1RaDkoNKFUvfxqAbtI8ncb8OJlqZ9wwpXzWPEsvsB1nvdUi6oYrHIkQ1Y/tMDnr1h4nczS0VB9Xykg==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "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, - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", - "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8.0" } }, - "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==", + "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" - }, - "node_modules/nest-winston": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/nest-winston/-/nest-winston-1.10.2.tgz", - "integrity": "sha512-Z9IzL/nekBOF/TEwBHUJDiDPMaXUcFquUQOFavIRet6xF0EbuWnOzslyN/ksgzG+fITNgXhMdrL/POp9SdaFxA==", - "license": "MIT", - "dependencies": { - "fast-safe-stringify": "^2.1.1" - }, - "peerDependencies": { - "@nestjs/common": "^5.0.0 || ^6.6.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0", - "winston": "^3.0.0" - } - }, - "node_modules/nestjs-i18n": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/nestjs-i18n/-/nestjs-i18n-10.6.0.tgz", - "integrity": "sha512-fPOgwrnb8u8UO6YXNlnamF7GDhNLOHQE8hD/pT/L7oUQibvL7PBZYZgquwppOFRaOPnH0uING2BzQGq7uQNNmQ==", "license": "MIT", "dependencies": { - "accept-language-parser": "^1.5.0", - "chokidar": "^3.6.0", - "cookie": "^0.7.0", - "iterare": "^1.2.1", - "js-yaml": "^4.1.0", - "string-format": "^2.0.0" + "@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": ">=18" - }, - "peerDependencies": { - "@nestjs/common": "*", - "@nestjs/core": "*", - "class-validator": "*", - "rxjs": "*" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/node-abort-controller": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", - "dev": true, + "node_modules/exsolve": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.8.tgz", + "integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==", + "devOptional": true, "license": "MIT" }, - "node_modules/node-addon-api": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz", - "integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==", + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, "license": "MIT", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, "engines": { - "node": "^18 || ^20 || >= 21" + "node": ">=4" } }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "deprecated": "Use your platform's native DOMException instead", + "node_modules/fast-check": { + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", + "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", + "devOptional": true, "funding": [ { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" }, { - "type": "github", - "url": "https://paypal.me/jimmywarting" + "type": "opencollective", + "url": "https://opencollective.com/fast-check" } ], "license": "MIT", - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-emoji": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", - "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash": "^4.17.21" - } - }, - "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 - } + "pure-rand": "^6.1.0" + }, + "engines": { + "node": ">=8.0.0" } }, - "node_modules/node-fetch-native": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", - "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "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/node-gyp-build": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", - "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", - "license": "MIT", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" }, - "node_modules/node-gyp-build-optional-packages": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", - "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", + "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", - "optional": true, "dependencies": { - "detect-libc": "^2.0.1" + "@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" }, - "bin": { - "node-gyp-build-optional-packages": "bin.js", - "node-gyp-build-optional-packages-optional": "optional.js", - "node-gyp-build-optional-packages-test": "build-test.js" + "engines": { + "node": ">=8.6.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==", + "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/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "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/nodemailer": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-8.0.3.tgz", - "integrity": "sha512-JQNBqvK+bj3NMhUFR3wmCl3SYcOeMotDiwDBvIoCuQdF0PvlIY0BH+FJ2CG7u4cXKPChplE78oowlH/Otsc4ZQ==", - "license": "MIT-0", - "engines": { - "node": ">=6.0.0" - } + "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==", + "license": "MIT" }, - "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "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, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" }, - "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==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "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/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==", + "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": "MIT", + "license": "Apache-2.0", "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" + "bser": "2.1.1" } }, - "node_modules/nypm": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.5.tgz", - "integrity": "sha512-K6AJy1GMVyfyMXRVB88700BJqNUkByijGJM8kEHpLdcAt+vSQAVfkWWHYzuRXHSY6xA2sNc5RjTj0p9rE2izVQ==", + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT" + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "license": "MIT", "dependencies": { - "citty": "^0.2.0", - "pathe": "^2.0.3", - "tinyexec": "^1.0.2" - }, - "bin": { - "nypm": "dist/cli.mjs" + "escape-string-regexp": "^1.0.5" }, "engines": { - "node": ">=18" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nypm/node_modules/citty": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/citty/-/citty-0.2.1.tgz", - "integrity": "sha512-kEV95lFBhQgtogAPlQfJJ0WGVSokvLr/UEoFPiKKOXF7pl98HfUVUD0ejsuTCld/9xH9vogSywZ5KqHzXrZpqg==", + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "license": "MIT" - }, - "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": ">=0.8.0" } }, - "node_modules/object-hash": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", - "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "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": ">= 6" + "node": "^10.12.0 || >=12.0.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==", + "node_modules/file-type": { + "version": "20.4.1", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-20.4.1.tgz", + "integrity": "sha512-hw9gNZXUfZ02Jo0uafWLaFVPter5/k2rfcrjFJJHX/77xtSDOfJuEFb6oKlFV86FLP1SuyHMW1PSk0U9M5tKkQ==", "license": "MIT", + "dependencies": { + "@tokenizer/inflate": "^0.2.6", + "strtok3": "^10.2.0", + "token-types": "^6.0.0", + "uint8array-extras": "^1.4.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sindresorhus/file-type?sponsor=1" } }, - "node_modules/obliterator": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.5.tgz", - "integrity": "sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==", - "license": "MIT" - }, - "node_modules/ohash": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", - "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "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" - }, - "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" + "to-regex-range": "^5.0.1" }, "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "node_modules/on-headers": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", - "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "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": ">= 0.8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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", + "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": { - "wrappy": "1" + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" } }, - "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==", + "node_modules/flat-cache/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, "license": "MIT", "dependencies": { - "fn.name": "1.x.x" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/flat-cache/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "mimic-fn": "^2.1.0" + "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": ">=6" + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/opossum": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/opossum/-/opossum-9.0.0.tgz", - "integrity": "sha512-K76U0QkxOfUZamneQuzz+AP0fyfTJcCplZ2oZL93nxeupuJbN4s6uFNbmVCt4eWqqGqRnnowdFuBicJ1fLMVxw==", - "license": "Apache-2.0", + "node_modules/flat-cache/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": "^24 || ^22 || ^20" + "node": "*" } }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "node_modules/flat-cache/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", "dev": true, - "license": "MIT", + "license": "ISC", "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" + "glob": "^7.1.3" }, - "engines": { - "node": ">= 0.8.0" + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true, - "license": "MIT", + "license": "ISC" + }, + "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==", + "dev": true, + "license": "ISC", "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "license": "MIT", + "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==", + "dev": true, + "license": "ISC", "engines": { - "node": ">=0.10.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "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==", + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", + "integrity": "sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==", + "dev": true, "license": "MIT", "dependencies": { - "yocto-queue": "^0.1.0" + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cosmiconfig": "^8.2.0", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" }, "engines": { - "node": ">=10" + "node": ">=12.13.0", + "yarn": ">=1.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" } }, - "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==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "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==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, "license": "MIT", "dependencies": { - "aggregate-error": "^3.0.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=12" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "*" } }, - "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==", + "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": ">=6" + "node": ">= 0.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/fs-monkey": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.1.0.tgz", + "integrity": "sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw==", + "dev": true, + "license": "Unlicense" }, - "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==", + "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==", + "dev": true, + "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", - "dependencies": { - "callsites": "^3.0.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "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, + "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", - "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" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "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": ">= 0.8" + "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==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/passport": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", - "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", + "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": { - "passport-strategy": "1.x.x", - "pause": "0.0.1", - "utils-merge": "^1.0.1" + "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.0" + "node": ">= 0.4" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/jaredhanson" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/passport-custom": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/passport-custom/-/passport-custom-1.1.1.tgz", - "integrity": "sha512-/2m7jUGxmCYvoqenLB9UrmkCgPt64h8ZtV+UtuQklZ/Tn1NpKBeOorCYkB/8lMRoiZ5hUrCoMmDtxCS/d38mlg==", + "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", - "dependencies": { - "passport-strategy": "1.x.x" - }, "engines": { - "node": ">= 0.10.0" + "node": ">=8.0.0" } }, - "node_modules/passport-jwt": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", - "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", + "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": { - "jsonwebtoken": "^9.0.0", - "passport-strategy": "^1.0.0" - } - }, - "node_modules/passport-local": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", - "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", - "dependencies": { - "passport-strategy": "1.x.x" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/passport-strategy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", - "engines": { - "node": ">= 0.4.0" + "node": ">= 0.4" } }, - "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==", + "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": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", - "dev": true, + "node_modules/giget": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", + "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", + "devOptional": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.0", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.6", + "nypm": "^0.6.0", + "pathe": "^2.0.3" + }, + "bin": { + "giget": "dist/cli.mjs" } }, - "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==", + "node_modules/giget/node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "devOptional": true, "license": "MIT", "engines": { - "node": ">=8" + "node": "^14.18.0 || >=16.10.0" } }, - "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==", - "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", + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "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" }, - "engines": { - "node": ">=16 || 14 >=14.18" + "bin": { + "glob": "dist/esm/bin.mjs" }, "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-to-regexp": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", - "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==", - "license": "MIT" - }, - "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==", + "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": "MIT", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true, - "license": "MIT" - }, - "node_modules/pause": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + "license": "BSD-2-Clause" }, - "node_modules/perfect-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", - "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "MIT" - }, - "node_modules/pg": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.17.2.tgz", - "integrity": "sha512-vjbKdiBJRqzcYw1fNU5KuHyYvdJ1qpcQg1CeBrHFqV1pWgHeVR6j/+kX0E1AAXfyuLUGY1ICrN2ELKA/z2HWzw==", - "license": "MIT", + "license": "ISC", "dependencies": { - "pg-connection-string": "^2.10.1", - "pg-pool": "^3.11.0", - "pg-protocol": "^1.11.0", - "pg-types": "2.2.0", - "pgpass": "1.0.5" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">= 16.0.0" - }, - "optionalDependencies": { - "pg-cloudflare": "^1.3.0" - }, - "peerDependencies": { - "pg-native": ">=3.0.1" + "node": ">=16 || 14 >=14.17" }, - "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.10.1", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.10.1.tgz", - "integrity": "sha512-iNzslsoeSH2/gmDDKiyMqF64DATUCWj3YJ0wP14kqcsf2TUklwimd+66yYojKwZCA7h2yRNLGug71hCBA2a4sw==", - "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.11.0", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.11.0.tgz", - "integrity": "sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w==", - "license": "MIT", - "peerDependencies": { - "pg": ">=8.0" - } - }, - "node_modules/pg-protocol": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.11.0.tgz", - "integrity": "sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g==", - "license": "MIT" + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "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==", + "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": { - "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" + "type-fest": "^0.20.2" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pgpass": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "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": { - "split2": "^4.1.0" + "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/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": "4.0.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.1.tgz", - "integrity": "sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==", - "dev": true, + "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": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pidtree": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "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==", + "dev": 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.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dev": true, "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, "bin": { - "pidtree": "bin/pidtree.js" + "handlebars": "bin/handlebars" }, "engines": { - "node": ">=0.10" + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" } }, - "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==", + "node_modules/handlebars/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/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "license": "MIT", "engines": { - "node": ">= 6" + "node": ">=8" } }, - "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==", + "node_modules/has-own-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", + "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==", "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==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "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": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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, + "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": { - "p-locate": "^4.1.0" + "function-bind": "^1.1.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "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==", + "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/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": { - "p-try": "^2.0.0" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { - "node": ">=6" + "node": ">= 0.8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "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==", + "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/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/pkg-types": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", - "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "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/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": { - "confbox": "^0.2.2", - "exsolve": "^1.0.7", - "pathe": "^2.0.3" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "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/pngjs": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", - "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "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": ">=10.13.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=0.8.19" } }, - "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/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.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" } }, - "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/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/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==", + "node_modules/inquirer": { + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", + "dev": true, "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^6.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=12.0.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==", + "node_modules/inquirer/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, "license": "MIT", "dependencies": { - "xtend": "^4.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "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, + "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.8.0" + "node": ">= 0.10" } }, - "node_modules/prettier": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.0.tgz", - "integrity": "sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA==", + "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", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } + "license": "MIT" }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", - "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", + "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": { - "fast-diff": "^1.1.2" + "binary-extensions": "^2.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=8" } }, - "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==", + "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": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "hasown": "^2.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "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": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/prisma": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.19.2.tgz", - "integrity": "sha512-XTKeKxtQElcq3U9/jHyxSPgiRgeYDKxWTPOf6NkXA0dNj5j40MfEsZkMbyNpwDWCUv7YBFUl7I2VK/6ALbmhEg==", + "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, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/config": "6.19.2", - "@prisma/engines": "6.19.2" - }, - "bin": { - "prisma": "build/index.js" - }, + "license": "MIT", "engines": { - "node": ">=18.18" - }, - "peerDependencies": { - "typescript": ">=5.1.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=6" } }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "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.6.0" + "node": ">=0.10.0" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true, - "license": "MIT" - }, - "node_modules/prom-client": { - "version": "15.1.3", - "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-15.1.3.tgz", - "integrity": "sha512-6ZiOBfCywsD4k1BN9IX0uZhF+tJkV8q8llP64G5Hajs4JOeVLPCwpPVcpXy3BwYiUGgyJzsJJQeOIv7+hDSq8g==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api": "^1.4.0", - "tdigest": "^0.1.1" - }, + "license": "MIT", "engines": { - "node": "^16 || ^18 || >=20" + "node": ">=8" } }, - "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==", + "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", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, "engines": { - "node": ">= 6" + "node": ">=0.12.0" } }, - "node_modules/proper-lockfile": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", - "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "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", - "dependencies": { - "graceful-fs": "^4.2.4", - "retry": "^0.12.0", - "signal-exit": "^3.0.2" + "engines": { + "node": ">=8" } }, - "node_modules/properties-reader": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/properties-reader/-/properties-reader-2.3.0.tgz", - "integrity": "sha512-z597WicA7nDZxK12kZqHr2TcvwNU1GCfA5UwfDY/HDp3hXPoPlb5rlEx9bwGTiJnc0OqbBTkU975jDToth8Gxw==", + "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==", "dev": true, "license": "MIT", - "dependencies": { - "mkdirp": "^1.0.4" - }, "engines": { - "node": ">=14" + "node": ">=8" }, "funding": { - "type": "github", - "url": "https://github.com/steveukx/properties?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/properties-reader/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/protobufjs": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", - "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", - "hasInstallScript": true, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "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", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, "engines": { - "node": ">=12.0.0" + "node": ">=8" } }, - "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", + "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": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" + "@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": ">= 0.10" + "node": ">=10" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" - }, - "node_modules/pump": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", - "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "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": "MIT", + "license": "BSD-3-Clause", "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", + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "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": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pure-rand": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", - "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "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, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" - }, - "node_modules/qrcode": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", - "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "dijkstrajs": "^1.0.1", - "pngjs": "^5.0.0", - "yargs": "^15.3.1" - }, - "bin": { - "qrcode": "bin/qrcode" + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" }, "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/qrcode/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/qrcode/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" + "node": ">=10" } }, - "node_modules/qrcode/node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "license": "MIT", + "node_modules/istanbul-lib-source-maps/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/qrcode/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==", - "license": "MIT", + "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": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/qrcode/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==", - "license": "MIT", + "node_modules/iterare": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", + "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==", + "license": "ISC", + "engines": { + "node": ">=6" + } + }, + "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==", + "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "p-locate": "^4.1.0" + "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/qrcode/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==", + "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": { - "p-try": "^2.0.0" + "@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": ">=6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/qrcode/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==", + "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": { - "p-limit": "^2.2.0" + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/qrcode/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "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": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "@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": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/qrcode/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "license": "ISC" - }, - "node_modules/qrcode/node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "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": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" + "@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": ">=8" + "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/qrcode/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "license": "ISC", + "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": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "@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": ">=6" + "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/qs": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", - "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", - "license": "BSD-3-Clause", + "node_modules/jest-config/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "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==", + "node_modules/jest-config/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/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" + "url": "https://github.com/sponsors/sibiraj-s" } ], - "license": "MIT" - }, - "node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, - "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": "2.5.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/rc9": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", - "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", - "dev": true, - "license": "MIT", - "dependencies": { - "defu": "^6.1.4", - "destr": "^2.0.3" - } - }, - "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/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "node_modules/jest-config/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" + "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": ">=8" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "node_modules/jest-config/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "*" } }, - "node_modules/read-pkg-up/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==", + "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": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/read-pkg-up/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==", + "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": { - "p-locate": "^4.1.0" + "detect-newline": "^3.0.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/read-pkg-up/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==", + "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": { - "p-try": "^2.0.0" + "@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": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/read-pkg-up/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==", + "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": { - "p-limit": "^2.2.0" + "@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": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "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 OR CC0-1.0)", + "license": "MIT", "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true, - "license": "ISC" - }, - "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "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": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "license": "(MIT OR CC0-1.0)", + "@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": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "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==", + "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": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">= 6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/readdir-glob": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", - "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "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": "Apache-2.0", + "license": "MIT", "dependencies": { - "minimatch": "^5.1.0" + "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/readdir-glob/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "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": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "@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": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "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": { - "picomatch": "^2.2.1" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=8.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "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": ">=8.6" + "node": ">=6" }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } } }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "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", - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/redis": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.7.1.tgz", - "integrity": "sha512-S1bJDnqLftzHXHP8JsT5II/CtHWQrASX5K96REjWjlmWKrviSOLWmM7QnRLstAWsu1VBBV1ffV6DzCvxNP0UJQ==", + "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", - "workspaces": [ - "./packages/*" - ], "dependencies": { - "@redis/bloom": "1.2.0", - "@redis/client": "1.6.1", - "@redis/graph": "1.1.1", - "@redis/json": "1.0.7", - "@redis/search": "1.2.0", - "@redis/time-series": "1.1.0" - } - }, - "node_modules/redis-errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", - "license": "MIT", + "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": ">=4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "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": { - "redis-errors": "^1.0.0" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" }, "engines": { - "node": ">=4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/reflect-metadata": { - "version": "0.1.14", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", - "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==", - "license": "Apache-2.0" - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "node_modules/jest-resolve/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.10" - } - }, - "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": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "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": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/require-in-the-middle": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-8.0.1.tgz", - "integrity": "sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.3.5", - "module-details-from-path": "^1.0.3" - }, + "node_modules/jest-runner/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": ">=9.3.0 || >=8.10.0 <9.0.0" + "node": ">=0.10.0" } }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "license": "ISC" - }, - "node_modules/resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "node_modules/jest-runner/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": { - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "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==", + "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": { - "resolve-from": "^5.0.0" + "@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": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-runtime/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/resolve-global": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", - "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "global-dirs": "^0.1.1" + "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": ">=8" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "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==", + "node_modules/jest-runtime/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=10" + "node": "*" } }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "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": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "@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": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "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": ">= 4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "node_modules/jest-util/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": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "node_modules/jest-util/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "license": "MIT" - }, - "node_modules/rimraf": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", - "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", - "license": "ISC", - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" + "license": "MIT", + "engines": { + "node": ">=8.6" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "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": ">=0.12.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "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, - "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/rxjs": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", - "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "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-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" + "@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": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "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": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "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": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 10.13.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/schema-utils/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "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.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "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" + "argparse": "^2.0.1" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/schema-utils/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "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", - "peerDependencies": { - "ajv": "^6.9.1" + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" } }, - "node_modules/schema-utils/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==", + "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/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "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": { - "semver": "bin/semver.js" + "json5": "lib/cli.js" }, "engines": { - "node": ">=10" + "node": ">=6" } }, - "node_modules/semver/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", + "node_modules/jsonc-parser": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.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": ">=10" + "node": ">=12", + "npm": ">=6" } }, - "node_modules/semver/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/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/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "license": "BSD-3-Clause", + "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": { - "randombytes": "^2.1.0" + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" } }, - "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/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/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==", + "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/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": { - "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" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, "engines": { - "node": ">= 0.4" + "node": ">= 0.8.0" } }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "node_modules/libphonenumber-js": { + "version": "1.12.34", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.34.tgz", + "integrity": "sha512-v/Ip8k8eYdp7bINpzqDh46V/PaQ8sK+qi97nMQgjZzFlb166YFqlR/HVI+MzsI9JqcyyVWCOipmmretiaSyQyw==", "license": "MIT" }, - "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/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/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" - }, + "node_modules/loader-runner": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", + "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">=6.11.5" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/sharp": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", - "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", - "hasInstallScript": true, - "license": "Apache-2.0", + "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": { - "color": "^4.2.3", - "detect-libc": "^2.0.3", - "semver": "^7.6.3" + "p-locate": "^5.0.0" }, "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=10" }, "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.33.5", - "@img/sharp-darwin-x64": "0.33.5", - "@img/sharp-libvips-darwin-arm64": "1.0.4", - "@img/sharp-libvips-darwin-x64": "1.0.4", - "@img/sharp-libvips-linux-arm": "1.0.5", - "@img/sharp-libvips-linux-arm64": "1.0.4", - "@img/sharp-libvips-linux-s390x": "1.0.4", - "@img/sharp-libvips-linux-x64": "1.0.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", - "@img/sharp-libvips-linuxmusl-x64": "1.0.4", - "@img/sharp-linux-arm": "0.33.5", - "@img/sharp-linux-arm64": "0.33.5", - "@img/sharp-linux-s390x": "0.33.5", - "@img/sharp-linux-x64": "0.33.5", - "@img/sharp-linuxmusl-arm64": "0.33.5", - "@img/sharp-linuxmusl-x64": "0.33.5", - "@img/sharp-wasm32": "0.33.5", - "@img/sharp-win32-ia32": "0.33.5", - "@img/sharp-win32-x64": "0.33.5" - } - }, - "node_modules/sharp/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" }, - "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/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/shimmer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", - "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", - "license": "BSD-2-Clause" + "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/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==", + "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.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.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/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, "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" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "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/magic-string": { + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", + "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" + "@jridgewell/sourcemap-codec": "^1.4.15" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=12" } }, - "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", + "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==", + "dev": true, + "license": "ISC" + }, + "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": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, + "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" - }, - "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==", + "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", - "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": ">= 0.6" } }, - "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==", + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", "dev": true, - "license": "ISC" - }, - "node_modules/simple-swizzle": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", - "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", - "license": "MIT", + "license": "Unlicense", "dependencies": { - "is-arrayish": "^0.3.1" + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" } }, - "node_modules/simple-swizzle/node_modules/is-arrayish": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", - "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", - "license": "MIT" - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "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/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "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": ">= 8" } }, - "node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "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": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "node": ">=8.6" } }, - "node_modules/slice-ansi/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==", + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", "engines": { - "node": ">=12" + "node": ">=8.6" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/solc": { - "version": "0.8.26", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.26.tgz", - "integrity": "sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==", + "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": { - "command-exists": "^1.2.8", - "commander": "^8.1.0", - "follow-redirects": "^1.12.1", - "js-sha3": "0.8.0", - "memorystream": "^0.3.1", - "semver": "^5.5.0", - "tmp": "0.0.33" - }, - "bin": { - "solcjs": "solc.js" + "mime-db": "1.52.0" }, "engines": { - "node": ">=10.0.0" + "node": ">= 0.6" } }, - "node_modules/solc/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "node_modules/mime-types/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": ">= 12" - } - }, - "node_modules/solc/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "license": "ISC", - "bin": { - "semver": "bin/semver" + "node": ">= 0.6" } }, - "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "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": "BSD-3-Clause", + "license": "MIT", "engines": { - "node": ">= 8" + "node": ">=6" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "license": "MIT", + "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": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/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==", - "license": "BSD-3-Clause", + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "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/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, - "license": "CC-BY-3.0" + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "license": "MIT", "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.22", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", - "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", - "dev": true, - "license": "CC0-1.0" + "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/speakeasy": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/speakeasy/-/speakeasy-2.0.0.tgz", - "integrity": "sha512-lW2A2s5LKi8rwu77ewisuUOtlCydF/hmQSOJjpTqTj1gZLkNgTaYnyvfxy2WBr4T/h+9c4g8HIITfj83OkFQFw==", + "node_modules/multer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz", + "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", "license": "MIT", "dependencies": { - "base32.js": "0.0.1" + "append-field": "^1.0.0", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "mkdirp": "^0.5.6", + "object-assign": "^4.1.1", + "type-is": "^1.6.18", + "xtend": "^4.0.2" }, "engines": { - "node": ">= 0.10.0" + "node": ">= 10.16.0" } }, - "node_modules/split-ca": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split-ca/-/split-ca-1.0.1.tgz", - "integrity": "sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ==", + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true, "license": "ISC" }, - "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/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/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "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": "BSD-3-Clause" + "license": "MIT" }, - "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" - } - ], + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-addon-api": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz", + "integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==", "license": "MIT", "engines": { - "node": ">=14" + "node": "^18 || ^20 || >= 21" } }, - "node_modules/ssh-remote-port-forward": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/ssh-remote-port-forward/-/ssh-remote-port-forward-1.0.4.tgz", - "integrity": "sha512-x0LV1eVDwjf1gmG7TTnfqIzf+3VPRz7vrNIjX6oYLbeCrf/PeVY6hkT68Mg+q02qXxQhrLjB0jfgvhevoCRmLQ==", + "node_modules/node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", "dev": true, "license": "MIT", "dependencies": { - "@types/ssh2": "^0.5.48", - "ssh2": "^1.4.0" + "lodash": "^4.17.21" } }, - "node_modules/ssh-remote-port-forward/node_modules/@types/ssh2": { - "version": "0.5.52", - "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-0.5.52.tgz", - "integrity": "sha512-lbLLlXxdCZOSJMCInKH2+9V/77ET2J6NPQHpFI0kda61Dd1KglJs+fPQBchizmzYSOJBgdTajhPqBO1xxLywvg==", - "dev": true, + "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": { - "@types/node": "*", - "@types/ssh2-streams": "*" - } - }, - "node_modules/ssh2": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.17.0.tgz", - "integrity": "sha512-wPldCk3asibAjQ/kziWQQt1Wh3PgDFpC0XpwclzKcdT1vql6KeYxf5LIt4nlFkUeR8WuphYMKqUA56X4rjbfgQ==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "asn1": "^0.2.6", - "bcrypt-pbkdf": "^1.0.2" + "whatwg-url": "^5.0.0" }, "engines": { - "node": ">=10.16.0" + "node": "4.x || >=6.0.0" }, - "optionalDependencies": { - "cpu-features": "~0.0.10", - "nan": "^2.23.0" + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" } }, - "node_modules/stack-chain": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/stack-chain/-/stack-chain-1.3.7.tgz", - "integrity": "sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug==", + "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.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, "license": "MIT" }, - "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==", + "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": "*" + "node": ">=0.10.0" } }, - "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==", + "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": { - "escape-string-regexp": "^2.0.0" + "path-key": "^3.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/stacktrace-parser": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz", - "integrity": "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==", + "node_modules/nypm": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.5.tgz", + "integrity": "sha512-K6AJy1GMVyfyMXRVB88700BJqNUkByijGJM8kEHpLdcAt+vSQAVfkWWHYzuRXHSY6xA2sNc5RjTj0p9rE2izVQ==", + "devOptional": true, "license": "MIT", "dependencies": { - "type-fest": "^0.7.1" + "citty": "^0.2.0", + "pathe": "^2.0.3", + "tinyexec": "^1.0.2" + }, + "bin": { + "nypm": "dist/cli.mjs" }, "engines": { - "node": ">=6" - } - }, - "node_modules/stacktrace-parser/node_modules/type-fest": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", - "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/standard-as-callback": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", - "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", + "node_modules/nypm/node_modules/citty": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.2.1.tgz", + "integrity": "sha512-kEV95lFBhQgtogAPlQfJJ0WGVSokvLr/UEoFPiKKOXF7pl98HfUVUD0ejsuTCld/9xH9vogSywZ5KqHzXrZpqg==", + "devOptional": true, "license": "MIT" }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "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.8" + "node": ">=0.10.0" } }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "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": ">=10.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/streamx": { - "version": "2.23.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", - "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "events-universal": "^1.0.0", - "fast-fifo": "^1.3.2", - "text-decoder": "^1.1.0" - } + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "devOptional": true, + "license": "MIT" }, - "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==", + "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": { - "safe-buffer": "~5.2.0" + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" } }, - "node_modules/string-argv": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", - "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "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==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.6.19" + "license": "ISC", + "dependencies": { + "wrappy": "1" } }, - "node_modules/string-format": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", - "integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==", - "license": "WTFPL OR MIT" - }, - "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==", + "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": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" + "mimic-fn": "^2.1.0" }, "engines": { - "node": ">=10" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "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": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "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": ">=8" + "node": ">= 0.8.0" } }, - "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==", + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" }, "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/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": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string-width/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==", + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "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==", + "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": { - "ansi-regex": "^5.0.1" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "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": { - "ansi-regex": "^5.0.1" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "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": ">=8" + "node": ">=6" } }, - "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==", + "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==", + "dev": true, + "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/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "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": { - "min-indent": "^1.0.0" + "@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/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==", + "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": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8" } }, - "node_modules/strtok3": { - "version": "10.3.4", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.4.tgz", - "integrity": "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==", + "node_modules/passport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", "license": "MIT", "dependencies": { - "@tokenizer/token": "^0.3.0" + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" }, "engines": { - "node": ">=18" + "node": ">= 0.4.0" }, "funding": { "type": "github", - "url": "https://github.com/sponsors/Borewit" + "url": "https://github.com/sponsors/jaredhanson" } }, - "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, + "node_modules/passport-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", "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" + "jsonwebtoken": "^9.0.0", + "passport-strategy": "^1.0.0" } }, - "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" - }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", "engines": { - "node": ">=6.4.0" + "node": ">= 0.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==", + "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", - "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==", + "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==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/swagger-ui-dist": { - "version": "5.17.14", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.14.tgz", - "integrity": "sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==", - "license": "Apache-2.0" - }, - "node_modules/symbol-observable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", - "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "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==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10" + "node": ">=8" } }, - "node_modules/synckit": { - "version": "0.11.12", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", - "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", + "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", + "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==", + "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "@pkgr/core": "^0.2.9" + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": ">=16 || 14 >=14.18" }, "funding": { - "url": "https://opencollective.com/synckit" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "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==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } + "license": "ISC" }, - "node_modules/tar-fs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", - "integrity": "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0", - "tar-stream": "^3.1.5" - }, - "optionalDependencies": { - "bare-fs": "^4.0.1", - "bare-path": "^3.0.0" - } + "node_modules/path-to-regexp": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", + "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==", + "license": "MIT" }, - "node_modules/tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "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", - "dependencies": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" + "engines": { + "node": ">=8" } }, - "node_modules/tdigest": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz", - "integrity": "sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==", - "license": "MIT", - "dependencies": { - "bintrees": "1.0.2" - } + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "devOptional": true, + "license": "MIT" }, - "node_modules/telejson": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/telejson/-/telejson-7.2.0.tgz", - "integrity": "sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==", - "license": "MIT", - "dependencies": { - "memoizerific": "^1.11.3" - } + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, - "node_modules/terser": { - "version": "5.46.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", - "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "devOptional": true, + "license": "MIT" }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.16", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", - "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", - "dev": true, + "node_modules/pg": { + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.17.2.tgz", + "integrity": "sha512-vjbKdiBJRqzcYw1fNU5KuHyYvdJ1qpcQg1CeBrHFqV1pWgHeVR6j/+kX0E1AAXfyuLUGY1ICrN2ELKA/z2HWzw==", "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", - "terser": "^5.31.1" + "pg-connection-string": "^2.10.1", + "pg-pool": "^3.11.0", + "pg-protocol": "^1.11.0", + "pg-types": "2.2.0", + "pgpass": "1.0.5" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 16.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "optionalDependencies": { + "pg-cloudflare": "^1.3.0" }, "peerDependencies": { - "webpack": "^5.1.0" + "pg-native": ">=3.0.1" }, "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { + "pg-native": { "optional": true } } }, - "node_modules/terser-webpack-plugin/node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": 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.10.1", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.10.1.tgz", + "integrity": "sha512-iNzslsoeSH2/gmDDKiyMqF64DATUCWj3YJ0wP14kqcsf2TUklwimd+66yYojKwZCA7h2yRNLGug71hCBA2a4sw==", + "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.11.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.11.0.tgz", + "integrity": "sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w==", "license": "MIT", - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" + "peerDependencies": { + "pg": ">=8.0" } }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "dev": true, + "node_modules/pg-protocol": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.11.0.tgz", + "integrity": "sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g==", + "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": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" + "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": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=4" } }, - "node_modules/terser-webpack-plugin/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, + "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": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "split2": "^4.1.0" } }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, - "license": "MIT" + "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==", + "node_modules/picomatch": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.1.tgz", + "integrity": "sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==", "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "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", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">= 6" } }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "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": "ISC", + "license": "MIT", "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" + "find-up": "^4.0.0" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=8" } }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "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": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/testcontainers": { - "version": "10.28.0", - "resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-10.28.0.tgz", - "integrity": "sha512-1fKrRRCsgAQNkarjHCMKzBKXSJFmzNTiTbhb5E/j5hflRXChEtHvkefjaHlgkNUjfw92/Dq8LTgwQn6RDBFbMg==", + "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": { - "@balena/dockerignore": "^1.0.2", - "@types/dockerode": "^3.3.35", - "archiver": "^7.0.1", - "async-lock": "^1.4.1", - "byline": "^5.0.0", - "debug": "^4.3.5", - "docker-compose": "^0.24.8", - "dockerode": "^4.0.5", - "get-port": "^7.1.0", - "proper-lockfile": "^4.1.2", - "properties-reader": "^2.3.0", - "ssh-remote-port-forward": "^1.0.4", - "tar-fs": "^3.0.7", - "tmp": "^0.2.3", - "undici": "^5.29.0" + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/testcontainers/node_modules/get-port": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-7.1.0.tgz", - "integrity": "sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==", + "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": ">=16" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/testcontainers/node_modules/tmp": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", - "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "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": ">=14.14" + "node": ">=8" } }, - "node_modules/text-decoder": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", - "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", - "dev": true, - "license": "Apache-2.0", + "node_modules/pkg-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "devOptional": true, + "license": "MIT", "dependencies": { - "b4a": "^1.6.4" + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" } }, - "node_modules/text-extensions": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", - "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "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/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true, - "license": "MIT" + "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/through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, + "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", - "dependencies": { - "readable-stream": "3" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/tinyexec": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", - "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", - "dev": true, + "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": ">=18" + "node": ">=0.10.0" } }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "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": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "xtend": "^4.0.0" }, "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" + "node": ">=0.10.0" } }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "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": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">= 0.8.0" } }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "node_modules/prettier": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.0.tgz", + "integrity": "sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA==", + "dev": true, "license": "MIT", - "dependencies": { - "os-tmpdir": "~1.0.2" + "bin": { + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=0.6.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "node_modules/prettier-linter-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", "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" + "fast-diff": "^1.1.2" }, "engines": { - "node": ">= 0.4" + "node": ">=6.0.0" } }, - "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==", + "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": { - "is-number": "^7.0.0" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">=8.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.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==", + "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": ">=0.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/token-types": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.2.tgz", - "integrity": "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==", - "license": "MIT", + "node_modules/prisma": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.19.2.tgz", + "integrity": "sha512-XTKeKxtQElcq3U9/jHyxSPgiRgeYDKxWTPOf6NkXA0dNj5j40MfEsZkMbyNpwDWCUv7YBFUl7I2VK/6ALbmhEg==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { - "@borewit/text-codec": "^0.2.1", - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" + "@prisma/config": "6.19.2", + "@prisma/engines": "6.19.2" + }, + "bin": { + "prisma": "build/index.js" }, "engines": { - "node": ">=14.16" + "node": ">=18.18" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "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/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "license": "MIT", - "bin": { - "tree-kill": "cli.js" + "peerDependencies": { + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "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": ">=8" + "node": ">= 6" } }, - "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==", + "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": ">= 14.0.0" + "node": ">= 0.10" } }, - "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==", + "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": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" + "node": ">=6" } }, - "node_modules/ts-jest": { - "version": "29.4.6", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.6.tgz", - "integrity": "sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==", - "dev": true, - "license": "MIT", + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "devOptional": 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.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "license": "BSD-3-Clause", "dependencies": { - "bs-logger": "^0.2.6", - "fast-json-stable-stringify": "^2.1.0", - "handlebars": "^4.7.8", - "json5": "^2.2.3", - "lodash.memoize": "^4.1.2", - "make-error": "^1.3.6", - "semver": "^7.7.3", - "type-fest": "^4.41.0", - "yargs-parser": "^21.1.1" - }, - "bin": { - "ts-jest": "cli.js" + "side-channel": "^1.1.0" }, "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 <6" + "node": ">=0.6" }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/transform": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true + "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" }, - "esbuild": { - "optional": true + { + "type": "patreon", + "url": "https://www.patreon.com/feross" }, - "jest-util": { - "optional": true + { + "type": "consulting", + "url": "https://feross.org/support" } - } + ], + "license": "MIT" }, - "node_modules/ts-jest/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" } }, - "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)", + "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": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.6" } }, - "node_modules/ts-loader": { - "version": "9.5.4", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.4.tgz", - "integrity": "sha512-nCz0rEwunlTZiy6rXFByQU1kVVpCIgUpc/psFiKVrUwrizdnIbRFu8w7bxhUF0X613DYwT4XzrZHpVyMe758hQ==", - "dev": true, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "license": "MIT", "dependencies": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4", - "source-map": "^0.7.4" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" }, "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "typescript": "*", - "webpack": "^5.0.0" + "node": ">= 0.8" } }, - "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==", - "dev": true, + "node_modules/rc9": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", + "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", + "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 - } + "defu": "^6.1.4", + "destr": "^2.0.3" } }, - "node_modules/ts-node/node_modules/diff": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", - "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", + "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": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } + "license": "MIT" }, - "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, + "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": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": ">=6" + "node": ">= 6" } }, - "node_modules/tsconfig-paths-webpack-plugin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.2.0.tgz", - "integrity": "sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==", + "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": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.7.0", - "tapable": "^2.2.1", - "tsconfig-paths": "^4.1.2" + "picomatch": "^2.2.1" }, "engines": { - "node": ">=10.13.0" + "node": ">=8.10.0" } }, - "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==", + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "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/tsort": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", - "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==", - "license": "MIT" - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "dev": true, - "license": "Unlicense" + "node_modules/reflect-metadata": { + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", + "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==", + "license": "Apache-2.0" }, - "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==", + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", "dev": true, "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, "engines": { - "node": ">= 0.8.0" + "node": ">=0.10" } }, - "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==", - "license": "(MIT OR CC0-1.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==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "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==", + "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", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "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==", + "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": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" + "resolve-from": "^5.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=8" } }, - "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/typedoc": { - "version": "0.28.18", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.18.tgz", - "integrity": "sha512-NTWTUOFRQ9+SGKKTuWKUioUkjxNwtS3JDRPVKZAXGHZy2wCA8bdv2iJiyeePn0xkmK+TCCqZFT0X7+2+FLjngA==", + "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": "Apache-2.0", - "dependencies": { - "@gerrit0/mini-shiki": "^3.23.0", - "lunr": "^2.3.9", - "markdown-it": "^14.1.1", - "minimatch": "^10.2.4", - "yaml": "^2.8.2" - }, - "bin": { - "typedoc": "bin/typedoc" - }, + "license": "MIT", "engines": { - "node": ">= 18", - "pnpm": ">= 10" - }, - "peerDependencies": { - "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x || 6.0.x" + "node": ">=8" } }, - "node_modules/typedoc-plugin-markdown": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.11.0.tgz", - "integrity": "sha512-2iunh2ALyfyh204OF7h2u0kuQ84xB3jFZtFyUr01nThJkLvR8oGGSSDlyt2gyO4kXhvUxDcVbO0y43+qX+wFbw==", + "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": ">= 18" - }, - "peerDependencies": { - "typedoc": "0.28.x" + "node": ">=10" } }, - "node_modules/typedoc/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==", + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, "engines": { - "node": "18 || 20 || >=22" + "node": ">=8" } }, - "node_modules/typedoc/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==", + "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", - "dependencies": { - "balanced-match": "^4.0.2" - }, "engines": { - "node": "18 || 20 || >=22" + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "node_modules/typedoc/node_modules/minimatch": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", - "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "ISC", "dependencies": { - "brace-expansion": "^5.0.2" + "glob": "^10.3.7" }, - "engines": { - "node": "18 || 20 || >=22" + "bin": { + "rimraf": "dist/esm/bin.mjs" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/typeorm": { - "version": "0.3.28", - "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.28.tgz", - "integrity": "sha512-6GH7wXhtfq2D33ZuRXYwIsl/qM5685WZcODZb7noOOcRMteM9KF2x2ap3H0EBjnSV0VO4gNAfJT5Ukp0PkOlvg==", + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, "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": ">=0.12.0" } }, - "node_modules/typeorm/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "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", @@ -19187,1453 +8580,1323 @@ ], "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "queue-microtask": "^1.2.2" } }, - "node_modules/typeorm/node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", - "license": "ISC", + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "license": "Apache-2.0", "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" + "tslib": "^2.1.0" } }, - "node_modules/typeorm/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", + "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/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/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">= 10.13.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/typeorm/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/typeorm/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" - ], + "node_modules/schema-utils/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "license": "MIT", - "bin": { - "uuid": "dist/esm/bin/uuid" + "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/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "node_modules/schema-utils/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" } }, - "node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "node_modules/schema-utils/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/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, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { - "uglifyjs": "bin/uglifyjs" + "semver": "bin/semver.js" }, "engines": { - "node": ">=0.8.0" + "node": ">=10" } }, - "node_modules/uid": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", - "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", - "license": "MIT", + "node_modules/semver/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", "dependencies": { - "@lukeed/csprng": "^1.0.0" + "yallist": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/uint8array-extras": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", - "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node_modules/semver/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/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" } }, - "node_modules/undici": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", - "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", + "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==", + "dev": true, "license": "MIT", "dependencies": { - "@fastify/busboy": "^2.0.0" + "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": ">=14.0" + "node": ">= 0.4" } }, - "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==", - "license": "MIT" + "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/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "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==", "dev": true, "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, "engines": { - "node": ">= 10.0.0" + "node": ">=8" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "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==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=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" - } - ], + "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": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" + "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" }, - "bin": { - "update-browserslist-db": "cli.js" + "engines": { + "node": ">= 0.4" }, - "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" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "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": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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/utils-merge": { + "node_modules/side-channel-map": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "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.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], + "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", - "bin": { - "uuid": "dist/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==", - "dev": 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" + "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": ">=10.12.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "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==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } + "license": "ISC" }, - "node_modules/validator": { - "version": "13.15.26", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.26.tgz", - "integrity": "sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA==", - "license": "MIT", - "engines": { - "node": ">= 0.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/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "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": ">= 0.8" + "node": ">=8" } }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "makeerror": "1.0.12" + "license": "BSD-3-Clause", + "engines": { + "node": ">= 8" } }, - "node_modules/watchpack": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", - "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "license": "MIT", "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "node_modules/source-map-support/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": "MIT", - "dependencies": { - "defaults": "^1.0.3" + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "license": "MIT", + "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": ">= 8" + "node": ">= 10.x" } }, - "node_modules/web3": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/web3/-/web3-4.16.0.tgz", - "integrity": "sha512-SgoMSBo6EsJ5GFCGar2E/pR2lcR/xmUSuQ61iK6yDqzxmm42aPPxSqZfJz2z/UCR6pk03u77pU8TGV6lgMDdIQ==", - "license": "LGPL-3.0", - "dependencies": { - "web3-core": "^4.7.1", - "web3-errors": "^1.3.1", - "web3-eth": "^4.11.1", - "web3-eth-abi": "^4.4.1", - "web3-eth-accounts": "^4.3.1", - "web3-eth-contract": "^4.7.2", - "web3-eth-ens": "^4.4.0", - "web3-eth-iban": "^4.0.7", - "web3-eth-personal": "^4.1.0", - "web3-net": "^4.1.0", - "web3-providers-http": "^4.2.0", - "web3-providers-ws": "^4.0.8", - "web3-rpc-methods": "^1.3.0", - "web3-rpc-providers": "^1.0.0-rc.4", - "web3-types": "^1.10.0", - "web3-utils": "^4.3.3", - "web3-validator": "^2.0.6" - }, - "engines": { - "node": ">=14.0.0", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-core": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-4.7.1.tgz", - "integrity": "sha512-9KSeASCb/y6BG7rwhgtYC4CvYY66JfkmGNEYb7q1xgjt9BWfkf09MJPaRyoyT5trdOxYDHkT9tDlypvQWaU8UQ==", - "license": "LGPL-3.0", - "dependencies": { - "web3-errors": "^1.3.1", - "web3-eth-accounts": "^4.3.1", - "web3-eth-iban": "^4.0.7", - "web3-providers-http": "^4.2.0", - "web3-providers-ws": "^4.0.8", - "web3-types": "^1.10.0", - "web3-utils": "^4.3.3", - "web3-validator": "^2.0.6" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - }, - "optionalDependencies": { - "web3-providers-ipc": "^4.0.7" - } + "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/web3-core/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "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": { - "@noble/hashes": "1.4.0" + "escape-string-regexp": "^2.0.0" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": ">=10" } }, - "node_modules/web3-core/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "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": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node": ">=8" } }, - "node_modules/web3-core/node_modules/ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "license": "MIT", - "dependencies": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" + "engines": { + "node": ">= 0.8" } }, - "node_modules/web3-core/node_modules/web3-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.3.tgz", - "integrity": "sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw==", - "license": "LGPL-3.0", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "eventemitter3": "^5.0.1", - "web3-errors": "^1.3.1", - "web3-types": "^1.10.0", - "web3-validator": "^2.0.6" - }, + "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": ">=14", - "npm": ">=6.12.0" + "node": ">=10.0.0" } }, - "node_modules/web3-errors": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/web3-errors/-/web3-errors-1.3.1.tgz", - "integrity": "sha512-w3NMJujH+ZSW4ltIZZKtdbkbyQEvBzyp3JRn59Ckli0Nz4VMsVq8aF1bLWM7A2kuQ+yVEm3ySeNU+7mSRwx7RQ==", - "license": "LGPL-3.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": { - "web3-types": "^1.10.0" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "safe-buffer": "~5.2.0" } }, - "node_modules/web3-eth": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-4.11.1.tgz", - "integrity": "sha512-q9zOkzHnbLv44mwgLjLXuyqszHuUgZWsQayD2i/rus2uk0G7hMn11bE2Q3hOVnJS4ws4VCtUznlMxwKQ+38V2w==", - "license": "LGPL-3.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": { - "setimmediate": "^1.0.5", - "web3-core": "^4.7.1", - "web3-errors": "^1.3.1", - "web3-eth-abi": "^4.4.1", - "web3-eth-accounts": "^4.3.1", - "web3-net": "^4.1.0", - "web3-providers-ws": "^4.0.8", - "web3-rpc-methods": "^1.3.0", - "web3-types": "^1.10.0", - "web3-utils": "^4.3.3", - "web3-validator": "^2.0.6" + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "node": ">=10" } }, - "node_modules/web3-eth-abi": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-4.4.1.tgz", - "integrity": "sha512-60ecEkF6kQ9zAfbTY04Nc9q4eEYM0++BySpGi8wZ2PD1tw/c0SDvsKhV6IKURxLJhsDlb08dATc3iD6IbtWJmg==", - "license": "LGPL-3.0", + "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==", + "dev": true, + "license": "MIT", "dependencies": { - "abitype": "0.7.1", - "web3-errors": "^1.3.1", - "web3-types": "^1.10.0", - "web3-utils": "^4.3.3", - "web3-validator": "^2.0.6" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "node": ">=8" } }, - "node_modules/web3-eth-abi/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "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==", + "dev": true, "license": "MIT", "dependencies": { - "@noble/hashes": "1.4.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": ">=8" } }, - "node_modules/web3-eth-abi/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "node_modules/string-width-cjs/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==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node": ">=8" } }, - "node_modules/web3-eth-abi/node_modules/ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "node_modules/string-width/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==", + "dev": true, "license": "MIT", - "dependencies": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" + "engines": { + "node": ">=8" } }, - "node_modules/web3-eth-abi/node_modules/web3-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.3.tgz", - "integrity": "sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw==", - "license": "LGPL-3.0", + "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==", + "dev": true, + "license": "MIT", "dependencies": { - "ethereum-cryptography": "^2.0.0", - "eventemitter3": "^5.0.1", - "web3-errors": "^1.3.1", - "web3-types": "^1.10.0", - "web3-validator": "^2.0.6" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "node": ">=8" } }, - "node_modules/web3-eth-accounts": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-4.3.1.tgz", - "integrity": "sha512-rTXf+H9OKze6lxi7WMMOF1/2cZvJb2AOnbNQxPhBDssKOllAMzLhg1FbZ4Mf3lWecWfN6luWgRhaeSqO1l+IBQ==", - "license": "LGPL-3.0", + "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==", + "dev": true, + "license": "MIT", "dependencies": { - "@ethereumjs/rlp": "^4.0.1", - "crc-32": "^1.2.2", - "ethereum-cryptography": "^2.0.0", - "web3-errors": "^1.3.1", - "web3-types": "^1.10.0", - "web3-utils": "^4.3.3", - "web3-validator": "^2.0.6" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "node": ">=8" } }, - "node_modules/web3-eth-accounts/node_modules/@ethereumjs/rlp": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", - "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==", - "license": "MPL-2.0", - "bin": { - "rlp": "bin/rlp" - }, + "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": ">=14" + "node": ">=8" } }, - "node_modules/web3-eth-accounts/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "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", - "dependencies": { - "@noble/hashes": "1.4.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": ">=6" } }, - "node_modules/web3-eth-accounts/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "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": ">= 16" + "node": ">=8" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/web3-eth-accounts/node_modules/ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "node_modules/strtok3": { + "version": "10.3.4", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.4.tgz", + "integrity": "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==", "license": "MIT", "dependencies": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" - } - }, - "node_modules/web3-eth-accounts/node_modules/web3-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.3.tgz", - "integrity": "sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw==", - "license": "LGPL-3.0", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "eventemitter3": "^5.0.1", - "web3-errors": "^1.3.1", - "web3-types": "^1.10.0", - "web3-validator": "^2.0.6" + "@tokenizer/token": "^0.3.0" }, "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/web3-eth-contract": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-4.7.2.tgz", - "integrity": "sha512-3ETqs2pMNPEAc7BVY/C3voOhTUeJdkf2aM3X1v+edbngJLHAxbvxKpOqrcO0cjXzC4uc2Q8Zpf8n8zT5r0eLnA==", - "license": "LGPL-3.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==", + "license": "MIT", "dependencies": { - "@ethereumjs/rlp": "^5.0.2", - "web3-core": "^4.7.1", - "web3-errors": "^1.3.1", - "web3-eth": "^4.11.1", - "web3-eth-abi": "^4.4.1", - "web3-types": "^1.10.0", - "web3-utils": "^4.3.3", - "web3-validator": "^2.0.6" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "node": ">=8" } }, - "node_modules/web3-eth-contract/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "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", - "dependencies": { - "@noble/hashes": "1.4.0" + "engines": { + "node": ">= 0.4" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/web3-eth-contract/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "node_modules/symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node": ">=0.10" } }, - "node_modules/web3-eth-contract/node_modules/ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "node_modules/synckit": { + "version": "0.11.12", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", + "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", + "dev": true, "license": "MIT", "dependencies": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" } }, - "node_modules/web3-eth-contract/node_modules/web3-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.3.tgz", - "integrity": "sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw==", - "license": "LGPL-3.0", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "eventemitter3": "^5.0.1", - "web3-errors": "^1.3.1", - "web3-types": "^1.10.0", - "web3-validator": "^2.0.6" - }, + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/web3-eth-ens": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-4.4.0.tgz", - "integrity": "sha512-DeyVIS060hNV9g8dnTx92syqvgbvPricE3MerCxe/DquNZT3tD8aVgFfq65GATtpCgDDJffO2bVeHp3XBemnSQ==", - "license": "LGPL-3.0", + "node_modules/terser": { + "version": "5.46.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", + "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@adraffy/ens-normalize": "^1.8.8", - "web3-core": "^4.5.0", - "web3-errors": "^1.2.0", - "web3-eth": "^4.8.0", - "web3-eth-contract": "^4.5.0", - "web3-net": "^4.1.0", - "web3-types": "^1.7.0", - "web3-utils": "^4.3.0", - "web3-validator": "^2.0.6" + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" }, "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "node": ">=10" } }, - "node_modules/web3-eth-ens/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "node_modules/terser-webpack-plugin": { + "version": "5.3.16", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", + "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", + "dev": true, "license": "MIT", "dependencies": { - "@noble/hashes": "1.4.0" + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/web3-eth-ens/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "license": "MIT", "engines": { - "node": ">= 16" + "node": ">= 10.13.0" }, "funding": { - "url": "https://paulmillr.com/funding/" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } } }, - "node_modules/web3-eth-ens/node_modules/ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "node_modules/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, "license": "MIT", "dependencies": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" - } - }, - "node_modules/web3-eth-ens/node_modules/web3-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.3.tgz", - "integrity": "sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw==", - "license": "LGPL-3.0", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "eventemitter3": "^5.0.1", - "web3-errors": "^1.3.1", - "web3-types": "^1.10.0", - "web3-validator": "^2.0.6" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "node": ">= 10.13.0" } }, - "node_modules/web3-eth-iban": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-4.0.7.tgz", - "integrity": "sha512-8weKLa9KuKRzibC87vNLdkinpUE30gn0IGY027F8doeJdcPUfsa4IlBgNC4k4HLBembBB2CTU0Kr/HAOqMeYVQ==", - "license": "LGPL-3.0", + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", + "dev": true, + "license": "MIT", "dependencies": { - "web3-errors": "^1.1.3", - "web3-types": "^1.3.0", - "web3-utils": "^4.0.7", - "web3-validator": "^2.0.3" + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" }, "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-eth-iban/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.4.0" + "node": ">= 10.13.0" }, "funding": { - "url": "https://paulmillr.com/funding/" + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/web3-eth-iban/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "node_modules/terser-webpack-plugin/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": ">= 16" + "node": ">=10" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/web3-eth-iban/node_modules/ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", - "license": "MIT", - "dependencies": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" - } + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" }, - "node_modules/web3-eth-iban/node_modules/web3-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.3.tgz", - "integrity": "sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw==", - "license": "LGPL-3.0", + "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": { - "ethereum-cryptography": "^2.0.0", - "eventemitter3": "^5.0.1", - "web3-errors": "^1.3.1", - "web3-types": "^1.10.0", - "web3-validator": "^2.0.6" + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" }, "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "node": ">=8" } }, - "node_modules/web3-eth-personal": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-4.1.0.tgz", - "integrity": "sha512-RFN83uMuvA5cu1zIwwJh9A/bAj0OBxmGN3tgx19OD/9ygeUZbifOL06jgFzN0t+1ekHqm3DXYQM8UfHpXi7yDQ==", - "license": "LGPL-3.0", + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", "dependencies": { - "web3-core": "^4.6.0", - "web3-eth": "^4.9.0", - "web3-rpc-methods": "^1.3.0", - "web3-types": "^1.8.0", - "web3-utils": "^4.3.1", - "web3-validator": "^2.0.6" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/web3-eth-personal/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", - "license": "MIT", + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", "dependencies": { - "@noble/hashes": "1.4.0" + "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" }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/web3-eth-personal/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "license": "MIT", "engines": { - "node": ">= 16" + "node": "*" }, "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/web3-eth-personal/node_modules/ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", - "license": "MIT", - "dependencies": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/web3-eth-personal/node_modules/web3-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.3.tgz", - "integrity": "sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw==", - "license": "LGPL-3.0", + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", "dependencies": { - "ethereum-cryptography": "^2.0.0", - "eventemitter3": "^5.0.1", - "web3-errors": "^1.3.1", - "web3-types": "^1.10.0", - "web3-validator": "^2.0.6" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "node": "*" } }, - "node_modules/web3-eth/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.4.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } + "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/web3-eth/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "devOptional": true, "license": "MIT", "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node": ">=18" } }, - "node_modules/web3-eth/node_modules/ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, "license": "MIT", "dependencies": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" - } - }, - "node_modules/web3-eth/node_modules/web3-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.3.tgz", - "integrity": "sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw==", - "license": "LGPL-3.0", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "eventemitter3": "^5.0.1", - "web3-errors": "^1.3.1", - "web3-types": "^1.10.0", - "web3-validator": "^2.0.6" + "os-tmpdir": "~1.0.2" }, "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "node": ">=0.6.0" } }, - "node_modules/web3-net": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-4.1.0.tgz", - "integrity": "sha512-WWmfvHVIXWEoBDWdgKNYKN8rAy6SgluZ0abyRyXOL3ESr7ym7pKWbfP4fjApIHlYTh8tNqkrdPfM4Dyi6CA0SA==", - "license": "LGPL-3.0", + "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-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": { - "web3-core": "^4.4.0", - "web3-rpc-methods": "^1.3.0", - "web3-types": "^1.6.0", - "web3-utils": "^4.3.0" + "is-number": "^7.0.0" }, "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "node": ">=8.0" } }, - "node_modules/web3-net/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "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", - "dependencies": { - "@noble/hashes": "1.4.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": ">=0.6" } }, - "node_modules/web3-net/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "node_modules/token-types": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.2.tgz", + "integrity": "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==", "license": "MIT", + "dependencies": { + "@borewit/text-codec": "^0.2.1", + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, "engines": { - "node": ">= 16" + "node": ">=14.16" }, "funding": { - "url": "https://paulmillr.com/funding/" + "type": "github", + "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/web3-net/node_modules/ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "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/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, "license": "MIT", - "dependencies": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" + "bin": { + "tree-kill": "cli.js" } }, - "node_modules/web3-net/node_modules/web3-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.3.tgz", - "integrity": "sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw==", - "license": "LGPL-3.0", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "eventemitter3": "^5.0.1", - "web3-errors": "^1.3.1", - "web3-types": "^1.10.0", - "web3-validator": "^2.0.6" - }, + "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": ">=14", - "npm": ">=6.12.0" + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" } }, - "node_modules/web3-providers-http": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-4.2.0.tgz", - "integrity": "sha512-IPMnDtHB7dVwaB7/mMxAZzyq7d5ezfO1+Vw0bNfAeIi7gaDlJiggp85SdyAfOgov8AMUA/dyiY72kQ0KmjXKvQ==", - "license": "LGPL-3.0", + "node_modules/ts-jest": { + "version": "29.4.6", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.6.tgz", + "integrity": "sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==", + "dev": true, + "license": "MIT", "dependencies": { - "cross-fetch": "^4.0.0", - "web3-errors": "^1.3.0", - "web3-types": "^1.7.0", - "web3-utils": "^4.3.1" + "bs-logger": "^0.2.6", + "fast-json-stable-stringify": "^2.1.0", + "handlebars": "^4.7.8", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.7.3", + "type-fest": "^4.41.0", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" }, "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "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 <6" + }, + "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/web3-providers-http/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.4.0" + "node_modules/ts-jest/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": ">=10" } }, - "node_modules/web3-providers-http/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "license": "MIT", + "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" + "node": ">=16" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/web3-providers-http/node_modules/ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "node_modules/ts-loader": { + "version": "9.5.4", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.4.tgz", + "integrity": "sha512-nCz0rEwunlTZiy6rXFByQU1kVVpCIgUpc/psFiKVrUwrizdnIbRFu8w7bxhUF0X613DYwT4XzrZHpVyMe758hQ==", + "dev": true, "license": "MIT", "dependencies": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" - } - }, - "node_modules/web3-providers-http/node_modules/web3-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.3.tgz", - "integrity": "sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw==", - "license": "LGPL-3.0", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "eventemitter3": "^5.0.1", - "web3-errors": "^1.3.1", - "web3-types": "^1.10.0", - "web3-validator": "^2.0.6" + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" }, "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-providers-ipc": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-4.0.7.tgz", - "integrity": "sha512-YbNqY4zUvIaK2MHr1lQFE53/8t/ejHtJchrWn9zVbFMGXlTsOAbNoIoZWROrg1v+hCBvT2c9z8xt7e/+uz5p1g==", - "license": "LGPL-3.0", - "optional": true, - "dependencies": { - "web3-errors": "^1.1.3", - "web3-types": "^1.3.0", - "web3-utils": "^4.0.7" + "node": ">=12.0.0" }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" } }, - "node_modules/web3-providers-ipc/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "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==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "@noble/hashes": "1.4.0" + "@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" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "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/web3-providers-ipc/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "license": "MIT", - "optional": true, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", + "dev": true, + "license": "BSD-3-Clause", "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node": ">=0.3.1" } }, - "node_modules/web3-providers-ipc/node_modules/ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "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", - "optional": true, "dependencies": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/web3-providers-ipc/node_modules/web3-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.3.tgz", - "integrity": "sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw==", - "license": "LGPL-3.0", - "optional": true, + "node_modules/tsconfig-paths-webpack-plugin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.2.0.tgz", + "integrity": "sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==", + "dev": true, + "license": "MIT", "dependencies": { - "ethereum-cryptography": "^2.0.0", - "eventemitter3": "^5.0.1", - "web3-errors": "^1.3.1", - "web3-types": "^1.10.0", - "web3-validator": "^2.0.6" + "chalk": "^4.1.0", + "enhanced-resolve": "^5.7.0", + "tapable": "^2.2.1", + "tsconfig-paths": "^4.1.2" }, "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "node": ">=10.13.0" } }, - "node_modules/web3-providers-ws": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-4.0.8.tgz", - "integrity": "sha512-goJdgata7v4pyzHRsg9fSegUG4gVnHZSHODhNnn6J93ykHkBI1nz4fjlGpcQLUMi4jAMz6SHl9Ibzs2jj9xqPw==", - "license": "LGPL-3.0", - "dependencies": { - "@types/ws": "8.5.3", - "isomorphic-ws": "^5.0.0", - "web3-errors": "^1.2.0", - "web3-types": "^1.7.0", - "web3-utils": "^4.3.1", - "ws": "^8.17.1" - }, + "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": ">=14", - "npm": ">=6.12.0" + "node": ">=4" } }, - "node_modules/web3-providers-ws/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, "license": "MIT", "dependencies": { - "@noble/hashes": "1.4.0" + "prelude-ls": "^1.2.1" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/web3-providers-ws/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "license": "MIT", + "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": ">= 16" + "node": ">=10" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/web3-providers-ws/node_modules/ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "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": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/web3-providers-ws/node_modules/web3-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.3.tgz", - "integrity": "sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw==", - "license": "LGPL-3.0", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "eventemitter3": "^5.0.1", - "web3-errors": "^1.3.1", - "web3-types": "^1.10.0", - "web3-validator": "^2.0.6" + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "license": "MIT" + }, + "node_modules/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", - "npm": ">=6.12.0" + "node": ">=14.17" } }, - "node_modules/web3-rpc-methods": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/web3-rpc-methods/-/web3-rpc-methods-1.3.0.tgz", - "integrity": "sha512-/CHmzGN+IYgdBOme7PdqzF+FNeMleefzqs0LVOduncSaqsppeOEoskLXb2anSpzmQAP3xZJPaTrkQPWSJMORig==", - "license": "LGPL-3.0", - "dependencies": { - "web3-core": "^4.4.0", - "web3-types": "^1.6.0", - "web3-validator": "^2.0.6" + "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": ">=14", - "npm": ">=6.12.0" + "node": ">=0.8.0" } }, - "node_modules/web3-rpc-providers": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/web3-rpc-providers/-/web3-rpc-providers-1.0.0-rc.4.tgz", - "integrity": "sha512-PXosCqHW0EADrYzgmueNHP3Y5jcSmSwH+Dkqvn7EYD0T2jcsdDAIHqk6szBiwIdhumM7gv9Raprsu/s/f7h1fw==", - "license": "LGPL-3.0", + "node_modules/uid": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", + "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", + "license": "MIT", "dependencies": { - "web3-errors": "^1.3.1", - "web3-providers-http": "^4.2.0", - "web3-providers-ws": "^4.0.8", - "web3-types": "^1.10.0", - "web3-utils": "^4.3.3", - "web3-validator": "^2.0.6" + "@lukeed/csprng": "^1.0.0" }, "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "node": ">=8" } }, - "node_modules/web3-rpc-providers/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "node_modules/uint8array-extras": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", + "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", "license": "MIT", - "dependencies": { - "@noble/hashes": "1.4.0" + "engines": { + "node": ">=18" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/web3-rpc-providers/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node": ">= 10.0.0" + } + }, + "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/web3-rpc-providers/node_modules/ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "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": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/web3-rpc-providers/node_modules/web3-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.3.tgz", - "integrity": "sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw==", - "license": "LGPL-3.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": { - "ethereum-cryptography": "^2.0.0", - "eventemitter3": "^5.0.1", - "web3-errors": "^1.3.1", - "web3-types": "^1.10.0", - "web3-validator": "^2.0.6" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "punycode": "^2.1.0" } }, - "node_modules/web3-types": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-types/-/web3-types-1.10.0.tgz", - "integrity": "sha512-0IXoaAFtFc8Yin7cCdQfB9ZmjafrbP6BO0f0KT/khMhXKUpoJ6yShrVhiNpyRBo8QQjuOagsWzwSK2H49I7sbw==", - "license": "LGPL-3.0", + "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/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "node": ">= 0.4.0" } }, - "node_modules/web3-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/web3-validator/-/web3-validator-2.0.6.tgz", - "integrity": "sha512-qn9id0/l1bWmvH4XfnG/JtGKKwut2Vokl6YXP5Kfg424npysmtRLe9DgiNBM9Op7QL/aSiaA0TVXibuIuWcizg==", - "license": "LGPL-3.0", + "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==", + "dev": 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": { - "ethereum-cryptography": "^2.0.0", - "util": "^0.12.5", - "web3-errors": "^1.2.0", - "web3-types": "^1.6.0", - "zod": "^3.21.4" + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" }, "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "node": ">=10.12.0" } }, - "node_modules/web3-validator/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "node_modules/validator": { + "version": "13.15.26", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.26.tgz", + "integrity": "sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA==", "license": "MIT", - "dependencies": { - "@noble/hashes": "1.4.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": ">= 0.10" } }, - "node_modules/web3-validator/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "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": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node": ">= 0.8" } }, - "node_modules/web3-validator/node_modules/ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", - "license": "MIT", + "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": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" + "makeerror": "1.0.12" } }, - "node_modules/web3/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "node_modules/watchpack": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", + "dev": true, "license": "MIT", "dependencies": { - "@noble/hashes": "1.4.0" + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/web3/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "license": "MIT", "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node": ">=10.13.0" } }, - "node_modules/web3/node_modules/ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, "license": "MIT", "dependencies": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" - } - }, - "node_modules/web3/node_modules/web3-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.3.tgz", - "integrity": "sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw==", - "license": "LGPL-3.0", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "eventemitter3": "^5.0.1", - "web3-errors": "^1.3.1", - "web3-types": "^1.10.0", - "web3-validator": "^2.0.6" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" + "defaults": "^1.0.3" } }, "node_modules/webidl-conversions": { @@ -20747,6 +10010,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -20758,114 +10022,6 @@ "node": ">= 8" } }, - "node_modules/which-module": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", - "license": "ISC" - }, - "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/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "license": "MIT", - "dependencies": { - "string-width": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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-daily-rotate-file": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/winston-daily-rotate-file/-/winston-daily-rotate-file-4.7.1.tgz", - "integrity": "sha512-7LGPiYGBPNyGHLn9z33i96zx/bd71pjBn9tqQzO3I4Tayv94WPmBNwKC7CO1wPHdP9uvu+Md/1nr6VSH9h0iaA==", - "license": "MIT", - "dependencies": { - "file-stream-rotator": "^0.6.1", - "object-hash": "^2.0.1", - "triple-beam": "^1.3.0", - "winston-transport": "^4.4.0" - }, - "engines": { - "node": ">=8" - }, - "peerDependencies": { - "winston": "^3" - } - }, - "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/winston/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/winston/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/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -20883,16 +10039,11 @@ "dev": true, "license": "MIT" }, - "node_modules/workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", - "license": "Apache-2.0" - }, "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==", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -20911,6 +10062,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -20928,6 +10080,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, "license": "ISC" }, "node_modules/write-file-atomic": { @@ -20944,56 +10097,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", - "dev": true, - "license": "MIT" - }, - "node_modules/xss": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.15.tgz", - "integrity": "sha512-FVdlVVC67WOIPvfOwhoMETV72f6GbW7aOabBC3WxN/oUdoEMDyLz4OgRv5/gck2ZeNqEQu+Tb0kloovXOfpYVg==", - "license": "MIT", - "dependencies": { - "commander": "^2.20.3", - "cssfilter": "0.0.10" - }, - "bin": { - "xss": "bin/xss" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/xss/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "license": "MIT" - }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -21007,6 +10110,7 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, "license": "ISC", "engines": { "node": ">=10" @@ -21019,25 +10123,11 @@ "dev": true, "license": "ISC" }, - "node_modules/yaml": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", - "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, "license": "MIT", "dependencies": { "cliui": "^8.0.1", @@ -21056,26 +10146,12 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, "license": "ISC", "engines": { "node": ">=12" } }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "license": "MIT", - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", @@ -21090,6 +10166,7 @@ "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" @@ -21097,72 +10174,6 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/zip-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", - "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==", - "dev": true, - "license": "MIT", - "dependencies": { - "archiver-utils": "^5.0.0", - "compress-commons": "^6.0.2", - "readable-stream": "^4.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/zip-stream/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "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": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/zip-stream/node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", - "dev": true, - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } } } } diff --git a/package.json b/package.json index 3698147c..5d22534e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "propchain-backend", "version": "1.0.0", - "description": "Decentralized Real Estate Infrastructure - Backend API for blockchain-powered property transactions", + "description": "PropChain - Blockchain-Powered Real Estate Platform", "author": "PropChain Team", "private": true, "license": "MIT", @@ -12,229 +12,66 @@ "start": "nest start", "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", - "start:ci": "cross-env NODE_ENV=test node dist/main", - "start:staging": "cross-env NODE_ENV=staging node dist/main", - "start:prod": "cross-env NODE_ENV=production node dist/main", + "start:prod": "node dist/main", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", - "test": "jest --config ./jest.config.js", - "lint:fix": "eslint . --ext .ts,.tsx,.js,.jsx --fix", - "format:check": "prettier --check .", - "test:watch": "jest --config ./jest.config.js --watch", - "test:cov": "jest --config ./jest.config.js --coverage --coverageReporters=text --coverageReporters=html --coverageReporters=lcov", - "test:unit": "jest --config ./jest.config.js --testPathPattern=spec", - "test:integration": "jest --config ./jest.config.js --testPathPattern=integration --passWithNoTests", - "test:e2e": "jest --config ./jest.config.js --testPathPattern=e2e --passWithNoTests", - "test:performance": "jest --config ./jest.config.js --testPathPattern=performance --passWithNoTests", - "test:security": "jest --config ./jest.config.js --testPathPattern=security --passWithNoTests", - "test:load": "jest --config ./jest.config.js --testPathPattern=load --passWithNoTests", - "test:contracts": "jest --config ./jest.config.js --testPathPattern=contracts", - "test:all": "npm run test:unit && npm run test:integration && npm run test:e2e && npm run test:security", - "test:comprehensive": "ts-node scripts/run-comprehensive-tests.ts", - "test:api-generation": "ts-node -r tsconfig-paths/register scripts/generate-api-tests.ts", - "test:contract-verification": "ts-node -r tsconfig-paths/register scripts/verify-contracts.ts", - "test:performance-suite": "ts-node -r tsconfig-paths/register scripts/run-performance-tests.ts", - "test:load-full": "ts-node -r tsconfig-paths/register scripts/run-load-tests.ts", - "test:stress": "ts-node -r tsconfig-paths/register scripts/run-stress-tests.ts", - "build:ci": "npx tsc -p tsconfig.ci.json --noEmit", - "test:ci": "jest --config ./jest.config.js --coverage --ci --reporters=default --reporters=jest-junit --watchAll=false", - "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --config ./jest.config.js --runInBand", - "test:clear": "jest --clearCache", - "test:update-snapshots": "jest --config ./jest.config.js --updateSnapshot", - "test:coverage:report": "jest --config ./jest.config.js --coverage --coverageReporters=text --coverageReporters=html --coverageReporters=cobertura", - "test:coverage:badge": "jest --config ./jest.config.js --coverage --coverageReporters=text-summary | grep 'All files' | cut -d' ' -f2 | cut -d'%' -f1", - "test:watch:unit": "jest --config ./jest.config.js --testPathPattern=spec --watch", - "test:watch:integration": "jest --config ./jest.config.js --testPathPattern=integration --watch", - "test:watch:e2e": "jest --config ./jest.config.js --testPathPattern=e2e --watch", + "test": "jest", + "test:watch": "jest --watch", + "test:cov": "jest --coverage", + "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", "migrate": "prisma migrate dev", "migrate:deploy": "prisma migrate deploy", "migrate:reset": "prisma migrate reset", - "migrate:validate": "node scripts/validate-migrations.js", - "migrate:rollback:dry-run": "node scripts/rollback-migration.js --dry-run", - "migrate:test": "npm run migrate:validate && jest --config ./jest.config.js --runInBand --testPathPattern=migration-safety.spec.ts", "db:seed": "ts-node prisma/seed.ts", "db:generate": "prisma generate", - "db:studio": "prisma studio", - "db:reset": "npm run migrate:reset && npm run db:seed", - "compile:contracts": "hardhat compile", - "deploy:testnet": "hardhat run scripts/deploy-testnet.ts --network sepolia", - "deploy:mainnet": "hardhat run scripts/deploy-mainnet.ts --network mainnet", - "verify:contracts": "hardhat verify --network", - "clean": "rimraf dist node_modules", - "health": "curl -f http://localhost:3000/api/v1/health/liveness || exit 1", - "db:backup": "bash scripts/backup.sh", - "db:restore": "bash scripts/restore.sh", - "db:benchmark": "ts-node test/database/performance.benchmark.ts", - "bench:middleware": "ts-node benchmarks/chains/run-benchmarks.ts", - "bench:middleware:quick": "ts-node benchmarks/chains/run-benchmarks.ts --iterations=100 --concurrency=5", - "bench:middleware:full": "ts-node benchmarks/chains/run-benchmarks.ts --iterations=5000 --concurrency=20", - "bench:memory": "node --expose-gc -r ts-node/register benchmarks/memory/run-memory-profile.ts", - "bench:memory:10k": "node --expose-gc -r ts-node/register benchmarks/memory/run-memory-profile.ts --requests=10000 --concurrency=50", - "loadtest:ci": "bash scripts/loadtest-ci.sh", - "docs:generate": "typedoc --skipErrorChecking" + "db:studio": "prisma studio" }, "dependencies": { - "@liaoliaots/nestjs-redis": "^10.0.0", - "@nestjs/bull": "^10.0.1", - "@nestjs/cache-manager": "^3.1.0", "@nestjs/common": "^10.3.0", "@nestjs/config": "^3.1.1", "@nestjs/core": "^10.3.0", - "@nestjs/jwt": "^11.0.2", - "@nestjs/passport": "^10.0.3", "@nestjs/platform-express": "^10.3.0", - "@nestjs/schedule": "^4.0.0", - "@nestjs/swagger": "^7.2.0", - "@nestjs/terminus": "^10.3.0", - "@nestjs/throttler": "^5.1.1", - "@nestjs/typeorm": "^10.0.2", - "@nomicfoundation/hardhat-toolbox": "^4.0.0", - "@opentelemetry/auto-instrumentations-node": "^0.70.1", - "@opentelemetry/exporter-otlp-grpc": "^0.45.1", - "@opentelemetry/resources": "^2.5.1", - "@opentelemetry/sdk-node": "^0.212.0", - "@opentelemetry/sdk-trace-base": "^1.18.1", - "@opentelemetry/sdk-trace-node": "^1.18.1", - "@opentelemetry/semantic-conventions": "^1.39.0", "@prisma/client": "^6.19.2", - "@types/nodemailer": "^7.0.11", - "@willsoto/nestjs-prometheus": "^6.0.2", - "aws-sdk": "^2.1500.0", - "@google-cloud/storage": "^7.7.0", - "@azure/storage-blob": "^12.17.0", - "axios": "^1.6.2", "bcrypt": "^6.0.0", - "bull": "^4.12.2", - "cache-manager": "^7.2.8", - "cache-manager-ioredis-yet": "^2.1.2", - "cache-manager-redis-store": "^3.0.1", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", - "cls-hooked": "^4.2.2", - "compression": "^1.7.4", - "cors": "^2.8.5", - "crypto-js": "^4.2.0", - "csv-parser": "^3.0.0", "dotenv": "^16.3.1", - "ethers": "^6.9.0", - "express-rate-limit": "^7.1.5", - "hardhat": "^2.19.4", - "helmet": "^7.1.0", - "ioredis": "^5.3.2", - "joi": "^17.11.0", "jsonwebtoken": "^9.0.2", - "lodash": "^4.17.21", - "mapped-types": "^0.0.1", - "moment": "^2.29.4", - "multer": "^2.0.2", - "nest-winston": "^1.10.2", - "nestjs-i18n": "^10.4.0", - "nodemailer": "^8.0.3", - "opossum": "^9.0.0", "passport": "^0.7.0", - "passport-custom": "^1.1.1", "passport-jwt": "^4.0.1", - "passport-local": "^1.0.0", - "passport-google-oauth20": "^2.0.0", - "passport-github2": "^0.1.12", - "passport-microsoft": "^1.0.0", - "passport-linkedin-oauth2": "^2.0.0", - "passport-saml": "^3.2.4", "pg": "^8.11.3", - "prom-client": "^15.1.3", - "qrcode": "^1.5.4", - "redis": "^4.6.12", "reflect-metadata": "^0.1.13", - "rxjs": "^7.8.1", - "sharp": "^0.33.1", - "speakeasy": "^2.0.0", - "typeorm": "^0.3.28", - "stellar-sdk": "^12.0.0", - "uuid": "^9.0.1", - "web3": "^4.3.0", - "winston": "^3.11.0", - "winston-daily-rotate-file": "^4.7.1", - "xml2js": "^0.6.2", - "xss": "^1.0.15", - "faker": "^6.6.6", - "jsonschema": "^1.4.1" + "rxjs": "^7.8.1" }, "devDependencies": { - "@commitlint/cli": "^18.4.3", - "@commitlint/config-conventional": "^18.4.3", "@nestjs/cli": "^10.3.0", "@nestjs/schematics": "^10.0.3", "@nestjs/testing": "^10.3.0", "@types/bcrypt": "^5.0.2", - "@types/compression": "^1.7.5", - "@types/cors": "^2.8.17", - "@types/crypto-js": "^4.2.1", "@types/express": "^4.17.21", - "@types/file-type": "^10.6.0", "@types/jest": "^29.5.14", - "@types/jsonwebtoken": "^9.0.5", - "@types/lodash": "^4.14.202", - "@types/multer": "^1.4.13", "@types/node": "^20.10.4", "@types/passport-jwt": "^3.0.13", - "@types/passport-local": "^1.0.38", - "@types/passport-google-oauth20": "^2.0.14", - "@types/passport-github2": "^1.2.9", - "@types/passport-microsoft": "^1.0.4", - "@types/passport-linkedin-oauth2": "^1.5.4", - "@types/passport-saml": "^3.2.9", - "@types/supertest": "^2.0.16", - "@types/uuid": "^9.0.7", - "@types/xml2js": "^0.4.14", - "@types/aws-sdk": "^2.7.0", "@typescript-eslint/eslint-plugin": "^6.13.1", "@typescript-eslint/parser": "^6.13.1", - "cross-env": "^10.1.0", "eslint": "^8.54.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-prettier": "^5.0.1", - "husky": "^8.0.3", "jest": "^29.7.0", - "jest-junit": "^16.0.0", - "lint-staged": "^15.2.0", "prettier": "^3.1.0", "prisma": "^6.19.2", "rimraf": "^5.0.5", "source-map-support": "^0.5.21", - "supertest": "^6.3.3", - "testcontainers": "^10.4.0", "ts-jest": "^29.4.6", "ts-loader": "^9.5.1", "ts-node": "^10.9.1", "tsconfig-paths": "^4.2.0", - "typedoc": "^0.28.18", - "typedoc-plugin-markdown": "^4.11.0", "typescript": "^5.3.2" }, "engines": { "node": ">=18.0.0", "npm": ">=8.0.0" }, - "keywords": [ - "nestjs", - "typescript", - "blockchain", - "web3", - "real-estate", - "propchain", - "ethereum", - "postgresql", - "redis", - "api" - ], "prisma": { "seed": "ts-node prisma/seed.ts" - }, - "repository": { - "type": "git", - "url": "https://github.com/MettaChain/PropChain-BackEnd.git" - }, - "bugs": { - "url": "https://github.com/MettaChain/PropChain-BackEnd/issues" - }, - "homepage": "https://github.com/MettaChain/PropChain-BackEnd#readme" + } } diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 6aa1668a..2992230f 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1,806 +1,170 @@ -// This is your Prisma schema file, -// learn more about it in the docs: https://pris.ly/d/prisma-schema +// PropChain - Real Estate Blockchain Platform +// Core Database Schema - -// Prisma client generator generator client { provider = "prisma-client-js" } - -// Database connection configuration datasource db { provider = "postgresql" url = env("DATABASE_URL") } -model User { - id String @id @default(cuid()) - email String @unique // Unique index for fast user lookup by email - walletAddress String? @unique @map("wallet_address") // Unique index for wallet address - role UserRole @default(USER) - roleId String? @map("role_id") - password String? - isVerified Boolean @default(false) @map("is_verified") - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - - // Advanced profile fields - bio String? - location String? - avatarUrl String? @map("avatar_url") - - // Preferences and privacy - preferences Json? - privacySettings Json? @map("privacy_settings") - exportRequestedAt DateTime? @map("export_requested_at") - - // Relationships - followers UserRelationship[] @relation("Followers") - following UserRelationship[] @relation("Following") - - // Activity - activities UserActivity[] - - // Password history for rotation policy - passwordHistory PasswordHistory[] - - properties Property[] - receivedTransactions Transaction[] @relation("UserTransactions") - userRole Role? @relation(fields: [roleId], references: [id], onDelete: SetNull) - roleChanges RoleChangeLog[] - documents Document[] - exportJobs ExportJob[] - reports PropertyReport[] - - // Indexes for common query patterns - @@index([email]) // For searching users by email - @@index([walletAddress]) // For searching users by wallet address - @@index([role]) // For filtering users by role - @@index([createdAt]) // For sorting/filtering by creation date - @@index([isVerified]) - @@index([location]) - @@map("users") -} - -// User activity tracking -model UserActivity { - id String @id @default(cuid()) - userId String @map("user_id") - action String - metadata Json? - createdAt DateTime @default(now()) @map("created_at") - - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@index([userId]) - @@index([action]) - @@index([createdAt]) - @@index([userId, action, createdAt(sort: Desc)]) - @@map("user_activities") -} - -// User relationship (followers, connections) -model UserRelationship { - id String @id @default(cuid()) - followerId String @map("follower_id") - followingId String @map("following_id") - status String @default("active") - createdAt DateTime @default(now()) @map("created_at") - - follower User @relation("Followers", fields: [followerId], references: [id], onDelete: Cascade) - following User @relation("Following", fields: [followingId], references: [id], onDelete: Cascade) - - @@unique([followerId, followingId]) - @@index([followerId]) - @@index([followingId]) - @@index([followingId, status, createdAt(sort: Desc)]) - @@index([followerId, status, createdAt(sort: Desc)]) - @@map("user_relationships") -} - -model Property { - id String @id @default(cuid()) - title String - description String? - location String - price Decimal - status PropertyStatus @default(DRAFT) - ownerId String @map("owner_id") - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - - // Soft delete fields for issues #258 and #259 - deletedAt DateTime? @map("deleted_at") - isDeleted Boolean @default(false) @map("is_deleted") - - // Valuation fields - estimatedValue Decimal? @map("estimated_value") - valuationDate DateTime? @map("valuation_date") - valuationConfidence Float? @map("valuation_confidence") - valuationSource String? @map("valuation_source") - lastValuationId String? @map("last_valuation_id") - - // Property features for valuation - bedrooms Int? - bathrooms Int? - squareFootage Decimal? @map("square_footage") - yearBuilt Int? @map("year_built") - propertyType String? @map("property_type") - lotSize Decimal? @map("lot_size") - - owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade) - transactions Transaction[] - valuations PropertyValuation[] - documents Document[] - withdrawals Withdrawal[] - - latitude Float? - longitude Float? - - rejectionReason String? @map("rejection_reason") - - // SEO metadata fields for issue #260 - metaTitle String? @map("meta_title") - metaDescription String? @map("meta_description") - metaKeywords String[] @map("meta_keywords") - - // Relationships - reports PropertyReport[] - versions PropertyVersion[] - availabilitySlots AvailabilitySlot[] - - // Indexes for geospatial queries and filtering - @@index([latitude, longitude]) // For location-based queries - @@index([ownerId]) // For filtering properties by owner - @@index([status]) // For filtering by property status - @@index([createdAt]) // For sorting/filtering by creation date - @@index([location]) // For searching/filtering by location - @@index([price]) // For price filtering/sorting - @@index([status, createdAt(sort: Desc)]) // For property listings by status and date - @@index([ownerId, createdAt(sort: Desc)]) // For owner's properties by date - @@index([status, price]) // For property search by status and price - @@index([isDeleted]) // For filtering soft-deleted properties - @@index([deletedAt]) // For cleanup of old soft-deleted properties - @@unique([ownerId, title, location]) // Prevent duplicate properties for same owner with same title and location - @@unique([latitude, longitude, ownerId]) // Prevent duplicate properties at same coordinates for same owner - @@map("properties") -} - -model PropertyValuation { - id String @id @default(cuid()) - propertyId String @map("property_id") - estimatedValue Decimal @map("estimated_value") - confidenceScore Float @map("confidence_score") - valuationDate DateTime @map("valuation_date") - source String - marketTrend String? @map("market_trend") - featuresUsed Json? @map("features_used") - rawData Json? @map("raw_data") - createdAt DateTime @default(now()) - - property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade) - - // Index for fast lookup by property and date - @@index([propertyId]) - @@index([valuationDate]) - @@index([propertyId, valuationDate(sort: Desc)]) - @@unique([propertyId, valuationDate, source]) // Prevent duplicate valuations for same property on same date from same source - @@map("property_valuations") -} - -model Transaction { - id String @id @default(cuid()) - fromAddress String @map("from_address") - toAddress String @map("to_address") - amount Decimal - txHash String? @unique @map("tx_hash") // Unique constraint for blockchain transaction hash - status TransactionStatus @default(PENDING) - type TransactionType - propertyId String? @map("property_id") - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - - buyerId String - sellerId String - currency String - blockchainHash String? @unique // Additional unique constraint for blockchain hash - blockNumber Int? - confirmations Int @default(0) - escrowWallet String? - gasFee Decimal? - platformFee Decimal? - disputeReason String? - - property Property? @relation(fields: [propertyId], references: [id], onDelete: SetNull) - recipient User? @relation("UserTransactions", fields: [toAddress], references: [walletAddress]) - documents Document[] - - // Indexes for common transaction queries - @@index([buyerId]) // For filtering by buyer - @@index([sellerId]) // For filtering by seller - @@index([fromAddress]) // For filtering by sender - @@index([toAddress]) // For filtering by recipient - @@index([status]) // For filtering by transaction status - @@index([createdAt]) // For sorting/filtering by creation date - @@index([propertyId]) // For filtering by property - @@index([txHash]) // For searching by transaction hash (redundant with unique but useful for queries) - @@index([blockchainHash]) // For searching by blockchain hash - @@index([blockNumber]) // For filtering by block number - @@index([confirmations]) // For filtering by confirmation count - @@unique([buyerId, sellerId, propertyId, amount, createdAt]) // Prevent duplicate transactions between same parties for same property - @@map("transactions") -} - -model Donation { - id String @id @default(cuid()) - provider String - providerTransactionId String @unique @map("provider_transaction_id") - amount Decimal - currency String - donorName String? @map("donor_name") - donorEmail String? @map("donor_email") - blockchainHash String? @map("blockchain_hash") - status DonationStatus @default(PENDING) - userId String? @map("user_id") - projectId String? @map("project_id") - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - - user User? @relation(fields: [userId], references: [id], onDelete: SetNull) - project Property? @relation(fields: [projectId], references: [id], onDelete: SetNull) - - @@index([provider]) - @@index([status]) - @@index([userId]) - @@index([projectId]) - @@map("donations") -} - -enum DonationStatus { - PENDING - CONFIRMED - FAILED -} - -enum WithdrawalStatus { - PENDING - APPROVED - REJECTED - PAID -} - -model Withdrawal { - id String @id @default(cuid()) - projectId String? @map("project_id") - amount Decimal - status WithdrawalStatus @default(PENDING) - transactionHash String? @map("transaction_hash") - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - - project Property? @relation(fields: [projectId], references: [id], onDelete: SetNull) - - @@index([projectId]) - @@map("withdrawals") -} - -model Role { - id String @id @default(cuid()) - name String @unique - description String? - level Int @default(0) - isSystem Boolean @default(false) @map("is_system") - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - - users User[] - permissions RolePermission[] - roleChangeLogs RoleChangeLog[] - - @@map("roles") -} - -model Permission { - id String @id @default(cuid()) - resource String - action String - description String? - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - - roles RolePermission[] - - @@unique([resource, action]) - @@map("permissions") -} - -model RolePermission { - id String @id @default(cuid()) - roleId String @map("role_id") - permissionId String @map("permission_id") - createdAt DateTime @default(now()) @map("created_at") - - role Role @relation(fields: [roleId], references: [id], onDelete: Cascade) - permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade) - - @@unique([roleId, permissionId]) - @@map("role_permissions") -} - -model RoleChangeLog { - id String @id @default(cuid()) - userId String @map("user_id") - roleId String @map("role_id") - oldRoleId String? @map("old_role_id") - changedBy String? @map("changed_by") - reason String? - createdAt DateTime @default(now()) @map("created_at") - - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - role Role @relation(fields: [roleId], references: [id], onDelete: Cascade) - - @@map("role_change_logs") -} - -model AuditLog { - id String @id @default(cuid()) - tableName String @map("table_name") - operation String - oldData Json? @map("old_data") - newData Json? @map("new_data") - userId String? @map("user_id") - timestamp DateTime @default(now()) - - @@index([timestamp(sort: Desc)]) - @@index([userId, timestamp(sort: Desc)]) - @@index([tableName, timestamp(sort: Desc)]) - @@index([operation, timestamp(sort: Desc)]) - @@map("audit_logs") -} - - -model SystemLog { - id String @id @default(cuid()) - logLevel String @map("log_level") - message String - context String? - timestamp DateTime @default(now()) - - @@index([timestamp(sort: Desc)]) - @@index([logLevel, timestamp(sort: Desc)]) - @@index([context, timestamp(sort: Desc)]) - @@map("system_logs") -} - - - - +// User roles in the system enum UserRole { - ADMIN - AGENT - SELLER - BUYER - VIEWER USER - VERIFIED_USER - MENTOR + AGENT + ADMIN } +// Property listing status enum PropertyStatus { DRAFT PENDING - APPROVED - LISTED + ACTIVE + UNDER_CONTRACT SOLD - REMOVED - PUBLISHED + RENTED + ARCHIVED +} + +// Transaction types +enum TransactionType { + SALE + PURCHASE + TRANSFER } +// Transaction status enum TransactionStatus { PENDING - PROCESSING COMPLETED - FAILED CANCELLED - - ESCROW_FUNDED - BLOCKCHAIN_SUBMITTED - CONFIRMING - CONFIRMED - DISPUTED - REFUNDED -} - -enum TransactionType { - PURCHASE - TRANSFER - ESCROW - REFUND + FAILED } +// Document types enum DocumentType { TITLE_DEED - OWNERSHIP_CERTIFICATE INSPECTION_REPORT APPRAISAL - INSURANCE - TAX_DOCUMENT CONTRACT - IDENTITY - OTHER -} - -enum DocumentStatus { - PENDING - VERIFIED - REJECTED - EXPIRED -} - -model Document { - id String @id @default(cuid()) - name String - type DocumentType - status DocumentStatus @default(PENDING) - fileUrl String @map("file_url") - fileHash String? @unique @map("file_hash") // Unique constraint for file hash to prevent duplicate uploads - mimeType String? @map("mime_type") - fileSize Int? @map("file_size") - description String? - propertyId String? @map("property_id") - transactionId String? @map("transaction_id") - uploadedById String @map("uploaded_by_id") - verifiedAt DateTime? @map("verified_at") - expiresAt DateTime? @map("expires_at") - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - - property Property? @relation(fields: [propertyId], references: [id], onDelete: SetNull) - transaction Transaction? @relation(fields: [transactionId], references: [id], onDelete: SetNull) - uploadedBy User @relation(fields: [uploadedById], references: [id], onDelete: Cascade) - - @@index([propertyId]) - @@index([transactionId]) - @@index([uploadedById]) - @@index([type]) - @@index([status]) - @@index([fileHash]) // Index for file hash lookups - @@index([createdAt]) - @@unique([propertyId, name, fileHash]) // Prevent duplicate documents for same property with same name and hash - @@unique([uploadedById, name, fileHash]) // Prevent duplicate uploads by same user with same name and hash - @@map("documents") -} - -model ApiKey { - id String @id @default(cuid()) - name String - key String @unique - keyPrefix String @map("key_prefix") - keyVersion Int @default(1) @map("key_version") - scopes String[] - requestCount BigInt @default(0) @map("request_count") - lastUsedAt DateTime? @map("last_used_at") - isActive Boolean @default(true) @map("is_active") - rateLimit Int? @map("rate_limit") - lastRotatedAt DateTime? @map("last_rotated_at") - rotationDueAt DateTime? @map("rotation_due_at") - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - - usageLogs ApiKeyUsageLog[] - - @@index([keyPrefix]) - @@index([isActive]) - @@index([createdAt]) - @@index([rotationDueAt]) - @@map("api_keys") -} - -model ApiKeyUsageLog { - id String @id @default(cuid()) - apiKeyId String @map("api_key_id") - endpoint String - method String - statusCode Int @map("status_code") - responseTime Int @map("response_time") - ipAddress String? @map("ip_address") - userAgent String? @map("user_agent") - createdAt DateTime @default(now()) @map("created_at") - - apiKey ApiKey @relation(fields: [apiKeyId], references: [id], onDelete: Cascade) - - @@index([apiKeyId]) - @@index([endpoint]) - @@index([createdAt]) - @@map("api_key_usage_logs") -} - -model PasswordHistory { - id String @id @default(cuid()) - userId String @map("user_id") - passwordHash String @map("password_hash") - createdAt DateTime @default(now()) @map("created_at") - - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@index([userId]) - @@index([createdAt]) - @@map("password_history") -} - -model ExportJob { - id String @id @default(cuid()) - userId String @map("user_id") - dataType String @map("data_type") - format String - status String @default("pending") - downloadUrl String? @map("download_url") - startDate DateTime? @map("start_date") - endDate DateTime? @map("end_date") - fields Json? // Array of field names - filters Json? // Export filters - totalRecords Int @default(0) @map("total_records") - fileSize Int? @map("file_size") - errorMessage String? @map("error_message") - createdAt DateTime @default(now()) @map("created_at") - startedAt DateTime? @map("started_at") - completedAt DateTime? @map("completed_at") - - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@index([userId]) - @@index([status]) - @@index([dataType]) - @@index([createdAt]) - @@index([completedAt]) - @@map("export_jobs") -} - -// KYC Verification model -model KycVerification { - id String @id @default(cuid()) - userId String @map("user_id") - providerReferenceId String @unique @map("provider_reference_id") - provider String - documentType String @map("document_type") - status KycStatus @default(PENDING) - riskScore Float? @map("risk_score") - verifiedAt DateTime? @map("verified_at") - expiresAt DateTime? @map("expires_at") - rejectionReason String? @map("rejection_reason") - metadata Json? - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@index([userId]) - @@index([status]) - @@index([providerReferenceId]) - @@index([createdAt]) - @@index([expiresAt]) - @@map("kyc_verifications") + DISCLOSURE + PHOTO + FLOOR_PLAN } -// AML Check model -model AmlCheck { - id String @id @default(cuid()) - userId String @map("user_id") - walletAddress String @map("wallet_address") - status AmlStatus @default(CLEAR) - sanctionsMatch Boolean @default(false) @map("sanctions_match") - pepMatch Boolean @default(false) @map("pep_match") - adverseMediaMatch Boolean @default(false) @map("adverse_media_match") - riskLevel String @map("risk_level") - riskScore Float @map("risk_score") - provider String - metadata Json? - screenedAt DateTime @map("screened_at") - createdAt DateTime @default(now()) @map("created_at") - - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@index([userId]) - @@index([walletAddress]) - @@index([status]) - @@index([screenedAt]) - @@map("aml_checks") -} - -// Compliance Alert model -model ComplianceAlert { - id String @id @default(cuid()) - userId String @map("user_id") - alertType String @map("alert_type") - severity AlertSeverity @default(MEDIUM) - status AlertStatus @default(OPEN) - details Json? - resolvedAt DateTime? @map("resolved_at") - resolvedBy String? @map("resolved_by") - resolution String? - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@index([userId]) - @@index([alertType]) - @@index([status]) - @@index([severity]) - @@index([createdAt]) - @@map("compliance_alerts") -} - -// Data Residency model -model DataResidency { - id String @id @default(cuid()) - userId String @unique @map("user_id") - preferredRegion String @map("preferred_region") - assignedRegion String @map("assigned_region") - countryCode String @map("country_code") - storageLocation String @map("storage_location") - crossBorderTransferAllowed Boolean @default(false) @map("cross_border_transfer_allowed") - applicableRegulations String[] @map("applicable_regulations") - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") +// User model +model User { + id String @id @default(uuid()) + email String @unique + password String + firstName String @map("first_name") + lastName String @map("last_name") + phone String? + role UserRole @default(USER) + isVerified Boolean @default(false) @map("is_verified") + avatar String? + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") - user User @relation(fields: [userId], references: [id], onDelete: Cascade) + // Relations + properties Property[] + buyerTransactions Transaction[] @relation("BuyerTransactions") + sellerTransactions Transaction[] @relation("SellerTransactions") + documents Document[] - @@index([userId]) - @@index([assignedRegion]) - @@index([countryCode]) - @@map("data_residencies") + @@index([email]) + @@index([role]) + @@map("users") } -// GDPR Request model -model GdprRequest { - id String @id @default(cuid()) - userId String @map("user_id") - requestType GdprRequestType @map("request_type") - status GdprRequestStatus @default(PENDING) - details String? - fields Json? - expectedCompletionDate DateTime @map("expected_completion_date") - completedAt DateTime? @map("completed_at") - resultData Json? @map("result_data") - failureReason String? @map("failure_reason") - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@index([userId]) - @@index([requestType]) +// Property model +model Property { + id String @id @default(uuid()) + title String + description String? + address String + city String + state String + zipCode String @map("zip_code") + country String @default("USA") + price Decimal + propertyType String @map("property_type") // House, Apartment, Condo, Land, etc. + bedrooms Int? + bathrooms Decimal? + squareFeet Decimal? @map("square_feet") + lotSize Decimal? @map("lot_size") + yearBuilt Int? @map("year_built") + status PropertyStatus @default(DRAFT) + ownerId String @map("owner_id") + latitude Float? + longitude Float? + features String[] // Array of features (pool, garage, etc.) + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + + // Relations + owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade) + transactions Transaction[] + documents Document[] + + @@index([ownerId]) @@index([status]) - @@index([createdAt]) - @@index([expectedCompletionDate]) - @@map("gdpr_requests") -} - -// Consent model -model Consent { - id String @id @default(cuid()) - userId String @map("user_id") - consentType String @map("consent_type") - granted Boolean @default(false) - grantedAt DateTime @map("granted_at") - withdrawnAt DateTime? @map("withdrawn_at") - version String @default("1.0") - ipAddress String? @map("ip_address") - userAgent String? @map("user_agent") - notes String? - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@index([userId]) - @@index([consentType]) - @@index([granted]) - @@unique([userId, consentType]) - @@map("consents") -} - -enum KycStatus { - PENDING - IN_REVIEW - VERIFIED - REJECTED - EXPIRED -} - -enum AmlStatus { - CLEAR - FLAGGED - UNDER_REVIEW - BLOCKED -} - -enum AlertSeverity { - LOW - MEDIUM - HIGH - CRITICAL -} - -enum AlertStatus { - OPEN - IN_PROGRESS - RESOLVED - CLOSED -} - -enum GdprRequestType { - DATA_EXPORT - DATA_DELETION - DATA_CORRECTION - CONSENT_WITHDRAWAL -} - -enum GdprRequestStatus { - PENDING - IN_PROGRESS - COMPLETED - FAILED + @@index([city, state]) + @@index([price]) + @@index([propertyType]) + @@map("properties") } -model PropertyReport { - id String @id @default(cuid()) - propertyId String @map("property_id") - reporterId String @map("reporter_id") - reason String - details String? - status ReportStatus @default(PENDING) - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - - property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade) - reporter User @relation(fields: [reporterId], references: [id], onDelete: Cascade) +// Transaction model +model Transaction { + id String @id @default(uuid()) + propertyId String @map("property_id") + buyerId String @map("buyer_id") + sellerId String @map("seller_id") + amount Decimal + type TransactionType + status TransactionStatus @default(PENDING) + blockchainHash String? @map("blockchain_hash") + contractAddress String? @map("contract_address") + notes String? + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + + // Relations + property Property @relation(fields: [propertyId], references: [id]) + buyer User @relation("BuyerTransactions", fields: [buyerId], references: [id]) + seller User @relation("SellerTransactions", fields: [sellerId], references: [id]) @@index([propertyId]) - @@index([reporterId]) + @@index([buyerId]) + @@index([sellerId]) @@index([status]) - @@map("property_reports") -} - -enum ReportStatus { - PENDING - UNDER_REVIEW - RESOLVED - DISMISSED -} - -model PropertyVersion { - id String @id @default(cuid()) - propertyId String @map("property_id") - versionNumber Int @map("version_number") - data Json - changedById String @map("changed_by_id") - changeReason String? @map("change_reason") - createdAt DateTime @default(now()) @map("created_at") - - property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade) - - @@index([propertyId]) - @@index([versionNumber]) - @@unique([propertyId, versionNumber]) - @@map("property_versions") + @@index([blockchainHash]) + @@map("transactions") } -model AvailabilitySlot { - id String @id @default(cuid()) - propertyId String @map("property_id") - startTime DateTime @map("start_time") - endTime DateTime @map("end_time") - isReserved Boolean @default(false) @map("is_reserved") - reservedById String? @map("reserved_by_id") - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - - property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade) +// Document model +model Document { + id String @id @default(uuid()) + propertyId String? @map("property_id") + userId String @map("user_id") + documentType DocumentType @map("document_type") + fileName String @map("file_name") + fileUrl String @map("file_url") + fileSize Int @map("file_size") // in bytes + mimeType String @map("mime_type") + description String? + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + + // Relations + property Property? @relation(fields: [propertyId], references: [id], onDelete: SetNull) + user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([propertyId]) - @@index([startTime, endTime]) - @@map("availability_slots") + @@index([userId]) + @@index([documentType]) + @@map("documents") } diff --git a/pw_test_out.txt b/pw_test_out.txt deleted file mode 100644 index 1fb856fb..00000000 --- a/pw_test_out.txt +++ /dev/null @@ -1,205 +0,0 @@ -npx : FAIL -test/common/password-rotation.service.spec.ts -(10.545 s) -At line:1 char:1 -+ npx jest -test/common/password-rotation.service.spec.ts ---config ./jes ... -+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -~~~~~~~~~~~~~~~~~~~~~~~ - + CategoryInfo : NotSpecified: (FA - IL test/commo...c.ts (10.545 s):String) [], - RemoteException - + FullyQualifiedErrorId : NativeCommandErro - r - - PasswordRotationService - ΓêÜ should be defined (24 ms) - checkRotationStatus - ΓêÜ should return canRotate false when -user not found (12 ms) - ΓêÜ should return canRotate false when -user has no password (9 ms) - ΓêÜ should return expired status when -password has expired (8 ms) - ├ù should return valid status with days -until expiry (12 ms) - ├ù should use password history date when -available (16 ms) - validatePasswordNotInHistory - ΓêÜ should return valid true when history -is empty (7 ms) - ΓêÜ should return valid true when -password not in history (7 ms) - ΓêÜ should return valid false when -password matches history (6 ms) - ΓêÜ should respect custom password -history count (7 ms) - addPasswordToHistory - ΓêÜ should add password to history and -not delete when under limit (6 ms) - ΓêÜ should delete old entries when over -limit (5 ms) - validatePasswordRotation - ΓêÜ should return invalid when rotation -status cannot rotate (5 ms) - ΓêÜ should return invalid when password -is in history (8 ms) - ΓêÜ should return valid when all checks -pass (7 ms) - getPasswordHistory - ΓêÜ should return password history with -default limit (6 ms) - ΓêÜ should return password history with -custom limit (6 ms) - ΓêÜ should select only required fields -(15 ms) - clearPasswordHistory - ΓêÜ should delete all password history -for user (6 ms) - getUsersWithExpiredPasswords - ΓêÜ should return empty array when no -users have expired passwords (6 ms) - ├ù should return users with expired -passwords (8 ms) - ├ù should use password history date for -expiry calculation (5 ms) - ΓêÜ should only include users with -passwords (5 ms) - requiresPasswordRotation - ΓêÜ should return false when user not -found (5 ms) - ΓêÜ should return false when user has no -password (5 ms) - ΓêÜ should return true when password is -expired (4 ms) - ΓêÜ should return true when within -warning period (7 ms) - ΓêÜ should return false when not in -warning period and not expired (6 ms) - ΓêÜ should use custom warning days from -config (7 ms) - - ΓùÅ PasswordRotationService ΓÇ║ -checkRotationStatus ΓÇ║ should return valid -status with days until expiry - - expect(received).toBe(expected) // -Object.is equality - - Expected: 60 - Received: 61 - -   126 | -  127 | expect(result. -[39mcanRotate).toBe(true)[3 -3m; - > 128 | e -xpect(result.daysUntilExpiry).[3 -9mtoBe(60); // 90 - -30 -  | - ^ -  129 | expect(result. -[39mreason).toBeUndefined(); -  130 | }); -  131 | - - at Object. (test/common/passwor -d-rotation.service.spec.ts:128:38) - - ΓùÅ PasswordRotationService ΓÇ║ -checkRotationStatus ΓÇ║ should use password -history date when available - - expect(received).toBe(expected) // -Object.is equality - - Expected: 60 - Received: 61 - -   148 | -  149 | expect(result. -[39mcanRotate).toBe(true)[3 -3m; - > 150 | e -xpect(result.daysUntilExpiry).[3 -9mtoBe(60); // 90 - 30 -(from password change date) -  | - ^ -  151 | expect(result. -[39mlastRotation).toEqual(passwordChan -geDate); -  152 | }); -  153 | }); - - at Object. (test/common/passwor -d-rotation.service.spec.ts:150:38) - - ΓùÅ PasswordRotationService ΓÇ║ -getUsersWithExpiredPasswords ΓÇ║ should return -users with expired passwords - - expect(received).toBe(expected) // -Object.is equality - - Expected: 10 - Received: 9 - -   399 | expect(result[[ -35m0].userId).toBe([32 -m'user-1'); -  400 | expect(result[0 -].email).toBe('exp -ired@example.com'); - > 401 | e -xpect(result[0].daysExpired) -.toBe(10); -// 100 - 90 -  | - ^ -  402 | }); -  403 | -  404 | it('should use -password history date for expiry -calculation', async () -=> { - - at Object. (test/common/passwor -d-rotation.service.spec.ts:401:37) - - ΓùÅ PasswordRotationService ΓÇ║ -getUsersWithExpiredPasswords ΓÇ║ should use -password history date for expiry calculation - - expect(received).toBe(expected) // -Object.is equality - - Expected: 10 - Received: 9 - -   422 | -  423 | expect(result). -toHaveLength(1); - > 424 | e -xpect(result[0].daysExpired) -.toBe(10); -// 100 - 90 -  | - ^ -  425 | }); -  426 | -  427 | it('should only -include users with passwords', -async () => { - - at Object. (test/common/passwor -d-rotation.service.spec.ts:424:37) - -Test Suites: 1 failed, 1 total -Tests: 4 failed, 25 passed, 29 total -Snapshots: 0 total -Time: 11.132 s, estimated 19 s -Ran all test suites matching /test\\common\\pass -word-rotation.service.spec.ts/i. diff --git a/reputation.module.ts b/reputation.module.ts deleted file mode 100644 index bfeafe38..00000000 --- a/reputation.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @fileoverview Module for handling reputation logic. - * @issue #207 - */ - -import { Module } from '@nestjs/common'; -import { ReputationService } from './reputation.service'; - -@Module({ - providers: [ReputationService], - exports: [ReputationService], -}) -export class ReputationModule {} \ No newline at end of file diff --git a/reputation.service.ts b/reputation.service.ts deleted file mode 100644 index 5aa59c69..00000000 --- a/reputation.service.ts +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @fileoverview Service for handling user reputation logic. - * This service is designed to be used within Prisma transactions to ensure atomicity. - * @issue #207 - */ - -import { Injectable, Logger } from '@nestjs/common'; -import { Prisma } from '@prisma/client'; -import { UpdateReputationDto } from './dto/update-reputation.dto'; - -type PrismaTransactionalClient = Omit< - Prisma.DefaultPrismaClient, - '$connect' | '$disconnect' | '$on' | '$transaction' | '$use' ->; - -@Injectable() -export class ReputationService { - private readonly logger = new Logger(ReputationService.name); - - /** - * Updates a user's reputation score and logs the action. - * This method is designed to be called within a Prisma transaction. - * - * @param tx - The Prisma transactional client. - * @param dto - The data for the reputation update. - */ - async updateReputationOnAction( - tx: PrismaTransactionalClient, - dto: UpdateReputationDto, - ): Promise { - const { userId, action, points } = dto; - - this.logger.log( - `Updating reputation for user ${userId} due to action '${action}' by ${points} points.`, - ); - - // Use the transactional client to update the user's reputation - await tx.user.update({ - where: { id: userId }, - data: { - reputation: { - increment: points, - }, - }, - }); - } -} \ No newline at end of file diff --git a/scripts/backup.sh b/scripts/backup.sh deleted file mode 100644 index 567e997a..00000000 --- a/scripts/backup.sh +++ /dev/null @@ -1,115 +0,0 @@ -#!/bin/bash - -# PropChain Database Backup Script -# Usage: ./backup.sh [backup_name] - -set -e - -# Configuration -BACKUP_DIR="${BACKUP_DIR:-./backups}" -TIMESTAMP=$(date +"%Y%m%d_%H%M%S") -BACKUP_NAME="${1:-propchain_backup_$TIMESTAMP}" -DATABASE_URL="${DATABASE_URL:-postgresql://postgres:password@localhost:5432/propchain}" - -# Parse DATABASE_URL -parse_db_url() { - local url="$1" - # Remove protocol - url="${url#postgresql://}" - - # Extract user:password - local auth="${url%%@*}" - DB_USER="${auth%%:*}" - DB_PASSWORD="${auth#*:}" - - # Extract host:port/database - url="${url#*@}" - local host_port="${url%%/*}" - DB_HOST="${host_port%%:*}" - DB_PORT="${host_port#*:}" - - # Extract database name (remove query params) - DB_NAME="${url#*/}" - DB_NAME="${DB_NAME%%\?*}" -} - -# Create backup directory if it doesn't exist -mkdir -p "$BACKUP_DIR" - -# Parse database URL -parse_db_url "$DATABASE_URL" - -echo "=== PropChain Database Backup ===" -echo "Timestamp: $TIMESTAMP" -echo "Database: $DB_NAME" -echo "Host: $DB_HOST:$DB_PORT" -echo "Backup Name: $BACKUP_NAME" -echo "" - -# Set password for pg_dump -export PGPASSWORD="$DB_PASSWORD" - -# Perform backup -echo "Creating backup..." -pg_dump \ - -h "$DB_HOST" \ - -p "$DB_PORT" \ - -U "$DB_USER" \ - -d "$DB_NAME" \ - -F c \ - -b \ - -v \ - -f "$BACKUP_DIR/$BACKUP_NAME.dump" - -# Create SQL format backup as well (for readability) -echo "Creating SQL backup..." -pg_dump \ - -h "$DB_HOST" \ - -p "$DB_PORT" \ - -U "$DB_USER" \ - -d "$DB_NAME" \ - --schema-only \ - -f "$BACKUP_DIR/${BACKUP_NAME}_schema.sql" - -pg_dump \ - -h "$DB_HOST" \ - -p "$DB_PORT" \ - -U "$DB_USER" \ - -d "$DB_NAME" \ - --data-only \ - -f "$BACKUP_DIR/${BACKUP_NAME}_data.sql" - -# Calculate checksum -echo "Calculating checksum..." -sha256sum "$BACKUP_DIR/$BACKUP_NAME.dump" > "$BACKUP_DIR/$BACKUP_NAME.sha256" - -# Validate backup -echo "Validating backup..." -if pg_restore -l "$BACKUP_DIR/$BACKUP_NAME.dump" > /dev/null 2>&1; then - echo "Backup validation passed: Dump is readable." -else - echo "ERROR: Backup validation failed: Dump is corrupted or unreadable!" - exit 1 -fi - -# Compress backup -echo "Compressing backup..." -gzip -k "$BACKUP_DIR/$BACKUP_NAME.dump" - -# Clean up old backups (keep last 10) -echo "Cleaning up old backups..." -cd "$BACKUP_DIR" -ls -t *.dump.gz 2>/dev/null | tail -n +11 | xargs -r rm -- -ls -t *.dump 2>/dev/null | tail -n +11 | xargs -r rm -- -ls -t *_schema.sql 2>/dev/null | tail -n +11 | xargs -r rm -- -ls -t *_data.sql 2>/dev/null | tail -n +11 | xargs -r rm -- -ls -t *.sha256 2>/dev/null | tail -n +11 | xargs -r rm -- - -echo "" -echo "=== Backup Complete ===" -echo "Files created:" -echo " - $BACKUP_DIR/$BACKUP_NAME.dump" -echo " - $BACKUP_DIR/$BACKUP_NAME.dump.gz" -echo " - $BACKUP_DIR/${BACKUP_NAME}_schema.sql" -echo " - $BACKUP_DIR/${BACKUP_NAME}_data.sql" -echo " - $BACKUP_DIR/$BACKUP_NAME.sha256" diff --git a/scripts/init-db.sql b/scripts/init-db.sql deleted file mode 100644 index 4855cfd3..00000000 --- a/scripts/init-db.sql +++ /dev/null @@ -1,165 +0,0 @@ --- PropChain Database Initialization Script --- This script sets up the initial database structure and extensions - --- Enable required extensions -CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -CREATE EXTENSION IF NOT EXISTS "pg_trgm"; -CREATE EXTENSION IF NOT EXISTS "btree_gin"; - --- Create custom types -CREATE TYPE user_role AS ENUM ('ADMIN', 'USER', 'VERIFIED_USER', 'AGENT'); -CREATE TYPE property_status AS ENUM ('DRAFT', 'PENDING', 'APPROVED', 'LISTED', 'SOLD', 'REMOVED'); -CREATE TYPE transaction_status AS ENUM ('PENDING', 'PROCESSING', 'COMPLETED', 'FAILED', 'CANCELLED'); -CREATE TYPE transaction_type AS ENUM ('PURCHASE', 'TRANSFER', 'ESCROW', 'REFUND'); - --- Create indexes for better performance -CREATE INDEX IF NOT EXISTS idx_users_email ON users(email); -CREATE INDEX IF NOT EXISTS idx_users_wallet_address ON users(wallet_address); -CREATE INDEX IF NOT EXISTS idx_properties_owner_id ON properties(owner_id); -CREATE INDEX IF NOT EXISTS idx_properties_status ON properties(status); -CREATE INDEX IF NOT EXISTS idx_properties_location ON properties USING GIN(to_tsvector('english', location)); -CREATE INDEX IF NOT EXISTS idx_transactions_from_address ON transactions(from_address); -CREATE INDEX IF NOT EXISTS idx_transactions_to_address ON transactions(to_address); -CREATE INDEX IF NOT EXISTS idx_transactions_status ON transactions(status); -CREATE INDEX IF NOT EXISTS idx_transactions_created_at ON transactions(created_at); - --- Create full-text search configuration -CREATE TEXT SEARCH CONFIGURATION IF NOT EXISTS propchain_search (COPY = english); - --- Set up row-level security policies (optional, for multi-tenant scenarios) --- ALTER TABLE properties ENABLE ROW LEVEL SECURITY; --- ALTER TABLE transactions ENABLE ROW LEVEL SECURITY; - --- Create audit trigger function -CREATE OR REPLACE FUNCTION audit_trigger_function() -RETURNS TRIGGER AS $$ -BEGIN - IF TG_OP = 'INSERT' THEN - INSERT INTO audit_logs(table_name, operation, old_data, new_data, user_id, timestamp) - VALUES(TG_TABLE_NAME, TG_OP, NULL, row_to_json(NEW), NULL, NOW()); - RETURN NEW; - ELSIF TG_OP = 'UPDATE' THEN - INSERT INTO audit_logs(table_name, operation, old_data, new_data, user_id, timestamp) - VALUES(TG_TABLE_NAME, TG_OP, row_to_json(OLD), row_to_json(NEW), NULL, NOW()); - RETURN NEW; - ELSIF TG_OP = 'DELETE' THEN - INSERT INTO audit_logs(table_name, operation, old_data, new_data, user_id, timestamp) - VALUES(TG_TABLE_NAME, TG_OP, row_to_json(OLD), NULL, NULL, NOW()); - RETURN OLD; - END IF; - RETURN NULL; -END; -$$ LANGUAGE plpgsql; - --- Create notification function for real-time updates -CREATE OR REPLACE FUNCTION notify_property_change() -RETURNS TRIGGER AS $$ -BEGIN - PERFORM pg_notify('property_changes', - json_build_object( - 'id', NEW.id, - 'status', NEW.status, - 'operation', TG_OP, - 'timestamp', NOW() - )::text - ); - RETURN NEW; -END; -$$ LANGUAGE plpgsql; - --- Create function for property search -CREATE OR REPLACE FUNCTION search_properties(query_text TEXT) -RETURNS TABLE( - id UUID, - title VARCHAR, - description TEXT, - location VARCHAR, - price DECIMAL, - status property_status, - similarity_score REAL -) AS $$ -BEGIN - RETURN QUERY - SELECT - p.id, - p.title, - p.description, - p.location, - p.price, - p.status, - ts_rank_cd( - to_tsvector('propchain_search', COALESCE(p.title, '') || ' ' || COALESCE(p.description, '') || ' ' || COALESCE(p.location, '')), - plainto_tsquery('propchain_search', query_text) - ) as similarity_score - FROM properties p - WHERE - to_tsvector('propchain_search', COALESCE(p.title, '') || ' ' || COALESCE(p.description, '') || ' ' || COALESCE(p.location, '')) - @@ plainto_tsquery('propchain_search', query_text) - AND p.status = 'APPROVED' - ORDER BY similarity_score DESC; -END; -$$ LANGUAGE plpgsql; - --- Create function for blockchain transaction verification -CREATE OR REPLACE FUNCTION verify_blockchain_transaction(tx_hash VARCHAR) -RETURNS TABLE( - verified BOOLEAN, - block_number BIGINT, - gas_used BIGINT, - status VARCHAR -) AS $$ -BEGIN - -- This would typically call an external service or use a blockchain library - -- For now, return a placeholder - RETURN QUERY - SELECT - false as verified, - 0::BIGINT as block_number, - 0::BIGINT as gas_used, - 'pending' as status; -END; -$$ LANGUAGE plpgsql; - --- Set up database statistics collection -CREATE OR REPLACE FUNCTION update_database_stats() -RETURNS VOID AS $$ -BEGIN - -- Update user statistics - ANALYZE users; - - -- Update property statistics - ANALYZE properties; - - -- Update transaction statistics - ANALYZE transactions; - - -- Log statistics update - INSERT INTO system_logs(log_level, message, context, timestamp) - VALUES('INFO', 'Database statistics updated', 'maintenance', NOW()); -END; -$$ LANGUAGE plpgsql; - --- Create scheduled job for statistics update (requires pg_cron extension) --- SELECT cron.schedule('update-stats', '0 2 * * *', 'SELECT update_database_stats();'); - --- Grant necessary permissions -GRANT USAGE ON SCHEMA public TO postgres; -GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO postgres; -GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO postgres; - --- Create initial admin user (optional - should be done through application) --- INSERT INTO users (id, email, wallet_address, role, created_at, updated_at) --- VALUES ( --- uuid_generate_v4(), --- 'admin@propchain.io', --- '0x0000000000000000000000000000000000000000', --- 'ADMIN', --- NOW(), --- NOW() --- ); - --- Log database initialization -INSERT INTO system_logs(log_level, message, context, timestamp) -VALUES('INFO', 'Database initialized successfully', 'setup', NOW()); - -COMMIT; diff --git a/scripts/loadtest-ci.sh b/scripts/loadtest-ci.sh deleted file mode 100755 index 95685bb8..00000000 --- a/scripts/loadtest-ci.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# k6 runs inside Docker; "localhost" / "127.0.0.1" in API_URL refer to the container, not the host. -# GitHub Actions often sets API_URL=http://localhost:3000 — rewrite so traffic reaches the app on the runner. -if [[ "${API_URL:-}" =~ ^https?://(localhost|127\.0\.0\.1)(:([0-9]+))?(/|$) ]]; then - PORT="${BASH_REMATCH[3]:-3000}" - export API_URL="http://host.docker.internal:${PORT}" -fi -export API_URL="${API_URL:-http://host.docker.internal:3000}" - -mkdir -p artifacts - -exec docker run --rm -i \ - --user "$(id -u):$(id -g)" \ - --add-host=host.docker.internal:host-gateway \ - -e "API_URL=${API_URL}" \ - -v "$PWD:/work" \ - -w /work \ - grafana/k6:latest run \ - --out json=artifacts/k6-results.json \ - loadtests/propchain-loadtest.js diff --git a/scripts/restore.sh b/scripts/restore.sh deleted file mode 100644 index 249e9333..00000000 --- a/scripts/restore.sh +++ /dev/null @@ -1,134 +0,0 @@ -#!/bin/bash - -# PropChain Database Restore Script -# Usage: ./restore.sh - -set -e - -# Configuration -DATABASE_URL="${DATABASE_URL:-postgresql://postgres:password@localhost:5432/propchain}" - -# Parse DATABASE_URL -parse_db_url() { - local url="$1" - # Remove protocol - url="${url#postgresql://}" - - # Extract user:password - local auth="${url%%@*}" - DB_USER="${auth%%:*}" - DB_PASSWORD="${auth#*:}" - - # Extract host:port/database - url="${url#*@}" - local host_port="${url%%/*}" - DB_HOST="${host_port%%:*}" - DB_PORT="${host_port#*:}" - - # Extract database name (remove query params) - DB_NAME="${url#*/}" - DB_NAME="${DB_NAME%%\?*}" -} - -# Check arguments -if [ -z "$1" ]; then - echo "Usage: $0 " - echo "" - echo "Examples:" - echo " $0 ./backups/propchain_backup_20250123_120000.dump" - echo " $0 ./backups/propchain_backup_20250123_120000.dump.gz" - exit 1 -fi - -BACKUP_FILE="$1" - -# Check if backup file exists -if [ ! -f "$BACKUP_FILE" ]; then - echo "Error: Backup file not found: $BACKUP_FILE" - exit 1 -fi - -# Parse database URL -parse_db_url "$DATABASE_URL" - -echo "=== PropChain Database Restore ===" -echo "Backup File: $BACKUP_FILE" -echo "Database: $DB_NAME" -echo "Host: $DB_HOST:$DB_PORT" -echo "" - -# Confirmation prompt -read -p "WARNING: This will overwrite all data in $DB_NAME. Continue? (yes/no): " confirm -if [ "$confirm" != "yes" ]; then - echo "Restore cancelled." - exit 0 -fi - -# Set password for psql/pg_restore -export PGPASSWORD="$DB_PASSWORD" - -# Decompress if necessary -RESTORE_FILE="$BACKUP_FILE" -if [[ "$BACKUP_FILE" == *.gz ]]; then - echo "Decompressing backup..." - RESTORE_FILE="${BACKUP_FILE%.gz}" - gunzip -k -f "$BACKUP_FILE" -fi - -# Verify checksum if available -CHECKSUM_FILE="${RESTORE_FILE}.sha256" -if [ -f "$CHECKSUM_FILE" ]; then - echo "Verifying checksum..." - if sha256sum -c "$CHECKSUM_FILE"; then - echo "Checksum verification passed." - else - echo "ERROR: Checksum verification failed!" - exit 1 - fi -fi - -# Drop existing connections -echo "Dropping existing connections..." -psql \ - -h "$DB_HOST" \ - -p "$DB_PORT" \ - -U "$DB_USER" \ - -d postgres \ - -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '$DB_NAME' AND pid <> pg_backend_pid();" \ - 2>/dev/null || true - -# Drop and recreate database -echo "Recreating database..." -psql \ - -h "$DB_HOST" \ - -p "$DB_PORT" \ - -U "$DB_USER" \ - -d postgres \ - -c "DROP DATABASE IF EXISTS $DB_NAME;" - -psql \ - -h "$DB_HOST" \ - -p "$DB_PORT" \ - -U "$DB_USER" \ - -d postgres \ - -c "CREATE DATABASE $DB_NAME;" - -# Restore backup -echo "Restoring backup..." -pg_restore \ - -h "$DB_HOST" \ - -p "$DB_PORT" \ - -U "$DB_USER" \ - -d "$DB_NAME" \ - -v \ - --no-owner \ - --no-privileges \ - "$RESTORE_FILE" - -# Run Prisma migrations to ensure schema is current -echo "Running Prisma migrations..." -npx prisma migrate deploy - -echo "" -echo "=== Restore Complete ===" -echo "Database $DB_NAME has been restored from $BACKUP_FILE" diff --git a/scripts/rollback-migration.js b/scripts/rollback-migration.js deleted file mode 100644 index 31c1bd47..00000000 --- a/scripts/rollback-migration.js +++ /dev/null @@ -1,89 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const { Client } = require('pg'); - -function parseArgs(argv) { - const args = { - name: undefined, - dryRun: false, - }; - - for (const arg of argv) { - if (arg.startsWith('--name=')) { - args.name = arg.slice('--name='.length); - } - - if (arg === '--dry-run') { - args.dryRun = true; - } - } - - return args; -} - -function getMigrationName(migrationsDir, requestedName) { - if (requestedName) { - return requestedName; - } - - const migrationDirs = fs - .readdirSync(migrationsDir, { withFileTypes: true }) - .filter(entry => entry.isDirectory()) - .map(entry => entry.name) - .sort(); - - return migrationDirs[migrationDirs.length - 1]; -} - -async function rollbackMigration({ repoRoot = process.cwd(), migrationName, dryRun = false }) { - const migrationsDir = path.join(repoRoot, 'prisma', 'migrations'); - const resolvedMigrationName = getMigrationName(migrationsDir, migrationName); - const rollbackPath = path.join(migrationsDir, resolvedMigrationName, 'rollback.sql'); - - if (!resolvedMigrationName) { - throw new Error('No migrations found.'); - } - - if (!fs.existsSync(rollbackPath)) { - throw new Error(`Rollback script not found for migration ${resolvedMigrationName}`); - } - - const rollbackSql = fs.readFileSync(rollbackPath, 'utf8'); - - if (dryRun) { - console.log(`Rollback plan for ${resolvedMigrationName}:\n`); - console.log(rollbackSql); - return; - } - - if (!process.env.DATABASE_URL) { - throw new Error('DATABASE_URL must be set to execute rollback.'); - } - - const client = new Client({ - connectionString: process.env.DATABASE_URL, - }); - - await client.connect(); - try { - await client.query(rollbackSql); - console.log(`Rollback applied for ${resolvedMigrationName}.`); - } finally { - await client.end(); - } -} - -if (require.main === module) { - const args = parseArgs(process.argv.slice(2)); - rollbackMigration({ - migrationName: args.name, - dryRun: args.dryRun, - }).catch(error => { - console.error(error.message); - process.exit(1); - }); -} - -module.exports = { - rollbackMigration, -}; diff --git a/scripts/run-comprehensive-tests.ts b/scripts/run-comprehensive-tests.ts deleted file mode 100644 index b0029bb4..00000000 --- a/scripts/run-comprehensive-tests.ts +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/env node - -import { NestFactory } from '@nestjs/core'; -import { AppModule } from '../src/app.module'; -import { TestingService } from '../src/services/TestingService'; -import { ConfigService } from '@nestjs/config'; - -async function runComprehensiveTests() { - console.log('🚀 Starting comprehensive API testing...'); - - let app; - try { - // Create NestJS application - app = await NestFactory.createApplicationContext(AppModule, { - logger: ['error', 'warn', 'log', 'debug'] - }); - - const testingService = app.get(TestingService); - const configService = app.get(ConfigService); - - console.log('📋 Available test suites:'); - const suites = testingService.getTestSuites(); - suites.forEach(suite => { - console.log(` - ${suite.name}: ${suite.description || 'No description'}`); - }); - - if (suites.length === 0) { - console.log('⚠️ No test suites found. Creating default suite...'); - - const defaultSuite = { - name: 'default-api-tests', - description: 'Default comprehensive API testing suite', - testGeneration: { - includeNegativeTests: true, - includeEdgeCases: true, - mockDataStrategy: 'realistic' - }, - contractTesting: { - enabled: true, - verificationOptions: { - timeout: 30000, - retries: 3 - } - }, - performanceTesting: { - enabled: true, - endpoints: [ - { - name: 'health-check', - method: 'GET', - url: configService.get('API_BASE_URL', 'http://localhost:3000') + '/api/v1/health', - weight: 10 - } - ], - thresholds: { - maxResponseTime: 1000, - minRequestsPerSecond: 100, - maxErrorRate: 1 - }, - config: { - duration: 60, - concurrency: 10 - } - } - }; - - await testingService.createTestSuite(defaultSuite); - console.log('✅ Default test suite created'); - } - - // Run health check first - console.log('🏥 Running health check...'); - const healthStatus = await testingService.runHealthCheck(); - console.log(`Health Status: ${healthStatus.status}`); - if (healthStatus.status !== 'healthy') { - console.log('⚠️ Health check failed. Tests may not run properly.'); - healthStatus.checks.forEach(check => { - if (!check.passed) { - console.log(` ❌ ${check.name}: ${check.error || 'Failed'}`); - } - }); - } - - // Execute test suites - const suiteName = process.argv[2] || suites[0]?.name || 'default-api-tests'; - console.log(`🧪 Executing test suite: ${suiteName}`); - - const startTime = Date.now(); - const result = await testingService.executeTestSuite(suiteName); - const duration = Date.now() - startTime; - - console.log('\n📊 Test Execution Results:'); - console.log(` Suite: ${result.suiteName}`); - console.log(` Duration: ${result.duration}ms`); - console.log(` Total Tests: ${result.summary.totalTests}`); - console.log(` Passed: ${result.summary.passedTests}`); - console.log(` Failed: ${result.summary.failedTests}`); - console.log(` Success Rate: ${result.summary.successRate.toFixed(2)}%`); - - if (result.generatedTests && result.generatedTests.length > 0) { - console.log(` Generated Tests: ${result.generatedTests.length}`); - } - - if (result.contractTests && result.contractTests.length > 0) { - const contractSummary = result.contractTests.reduce((acc, suite) => ({ - total: acc.total + suite.summary.total, - passed: acc.passed + suite.summary.passed, - failed: acc.failed + suite.summary.failed - }), { total: 0, passed: 0, failed: 0 }); - - console.log(` Contract Tests: ${contractSummary.total} (${contractSummary.passed} passed, ${contractSummary.failed} failed)`); - } - - if (result.performanceReport) { - const perf = result.performanceReport.summary; - console.log(` Performance Tests:`); - console.log(` Overall RPS: ${perf.overallRps.toFixed(2)}`); - console.log(` Avg Response Time: ${perf.averageResponseTime.toFixed(2)}ms`); - console.log(` Error Rate: ${perf.errorRate.toFixed(2)}%`); - console.log(` Success Rate: ${perf.successRate.toFixed(2)}%`); - } - - if (result.errors.length > 0) { - console.log('\n❌ Errors:'); - result.errors.forEach(error => { - console.log(` - ${error}`); - }); - } - - // Generate comprehensive report - console.log('\n📄 Generating comprehensive report...'); - const report = await testingService.generateComprehensiveReport(); - - const reportPath = `test-reports/comprehensive-report-${Date.now()}.md`; - require('fs').writeFileSync(reportPath, report); - console.log(`📋 Report saved to: ${reportPath}`); - - // Exit with appropriate code - if (result.summary.failedTests > 0) { - console.log('\n❌ Some tests failed'); - process.exit(1); - } else { - console.log('\n✅ All tests passed successfully!'); - process.exit(0); - } - - } catch (error) { - console.error('❌ Error running comprehensive tests:', error); - process.exit(1); - } finally { - if (app) { - await app.close(); - } - } -} - -// Handle unhandled promise rejections -process.on('unhandledRejection', (reason, promise) => { - console.error('Unhandled Rejection at:', promise, 'reason:', reason); - process.exit(1); -}); - -// Run the comprehensive tests -runComprehensiveTests(); diff --git a/scripts/test-restore.sh b/scripts/test-restore.sh deleted file mode 100644 index a13b3c4b..00000000 --- a/scripts/test-restore.sh +++ /dev/null @@ -1,115 +0,0 @@ -#!/bin/bash - -# PropChain Database Restore Testing Script -# Usage: ./test-restore.sh - -set -e - -# Configuration -DATABASE_URL="${DATABASE_URL:-postgresql://postgres:password@localhost:5432/propchain}" -TEST_DB_NAME="propchain_test_restore_$(date +%s)" - -# Parse DATABASE_URL -parse_db_url() { - local url="$1" - # Remove protocol - url="${url#postgresql://}" - - # Extract user:password - local auth="${url%%@*}" - DB_USER="${auth%%:*}" - DB_PASSWORD="${auth#*:}" - - # Extract host:port/database - url="${url#*@}" - local host_port="${url%%/*}" - DB_HOST="${host_port%%:*}" - DB_PORT="${host_port#*:}" -} - -# Check arguments -if [ -z "$1" ]; then - echo "Usage: $0 " - exit 1 -fi - -BACKUP_FILE="$1" - -# Check if backup file exists -if [ ! -f "$BACKUP_FILE" ]; then - echo "Error: Backup file not found: $BACKUP_FILE" - exit 1 -fi - -# Parse database URL -parse_db_url "$DATABASE_URL" - -echo "=== PropChain Backup Restoration Test ===" -echo "Backup File: $BACKUP_FILE" -echo "Test Database: $TEST_DB_NAME" -echo "" - -# Set password for psql/pg_restore -export PGPASSWORD="$DB_PASSWORD" - -# Decompress if necessary -RESTORE_FILE="$BACKUP_FILE" -TEMP_FILE="" -if [[ "$BACKUP_FILE" == *.gz ]]; then - echo "Decompressing backup..." - RESTORE_FILE="$(mktemp --suffix=.dump)" - TEMP_FILE="$RESTORE_FILE" - gunzip -c "$BACKUP_FILE" > "$RESTORE_FILE" -fi - -# Create test database -echo "Creating test database $TEST_DB_NAME..." -psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "CREATE DATABASE $TEST_DB_NAME;" - -# Function to clean up -cleanup() { - echo "Cleaning up..." - psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "DROP DATABASE IF EXISTS $TEST_DB_NAME;" - if [ -n "$TEMP_FILE" ] && [ -f "$TEMP_FILE" ]; then - rm "$TEMP_FILE" - fi -} - -trap cleanup EXIT - -# Restore backup to test database -echo "Restoring backup to test database..." -pg_restore \ - -h "$DB_HOST" \ - -p "$DB_PORT" \ - -U "$DB_USER" \ - -d "$TEST_DB_NAME" \ - --no-owner \ - --no-privileges \ - "$RESTORE_FILE" > /dev/null 2>&1 - -# Run verification checks -echo "Running verification checks..." - -# Check 1: Can we connect? -psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$TEST_DB_NAME" -c "SELECT 1;" > /dev/null - -# Check 2: Check for essential tables (e.g., users) -TABLE_COUNT=$(psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$TEST_DB_NAME" -t -c "SELECT count(*) FROM information_schema.tables WHERE table_schema = 'public';") -echo "Found $TABLE_COUNT tables in restored database." - -if [ "$TABLE_COUNT" -lt 5 ]; then - echo "ERROR: Too few tables found ($TABLE_COUNT). Restore might have failed." - exit 1 -fi - -# Check 3: Check data in key tables -# We use -t to get only the value -USER_COUNT=$(psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$TEST_DB_NAME" -t -c "SELECT count(*) FROM \"users\";" | xargs) -PROPERTY_COUNT=$(psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$TEST_DB_NAME" -t -c "SELECT count(*) FROM \"properties\";" | xargs) - -echo "Restored User Count: $USER_COUNT" -echo "Restored Property Count: $PROPERTY_COUNT" - -echo "" -echo "=== Restoration Test Successful ===" diff --git a/scripts/validate-migrations.js b/scripts/validate-migrations.js deleted file mode 100644 index 41dfdd46..00000000 --- a/scripts/validate-migrations.js +++ /dev/null @@ -1,123 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -const BREAKING_CHANGE_MARKER = '-- @allow-breaking-change'; -const BLOCKING_INDEX_MARKER = '-- @allow-blocking-index'; - -const breakingPatterns = [ - { - regex: /\bDROP\s+TABLE\b/i, - message: 'DROP TABLE is not backward-compatible. Use expand/contract and a later cleanup migration.', - }, - { - regex: /\bDROP\s+COLUMN\b/i, - message: 'DROP COLUMN is not backward-compatible. Keep the old column until all application versions stop reading it.', - }, - { - regex: /\bRENAME\s+COLUMN\b/i, - message: 'RENAME COLUMN is not backward-compatible. Add the new column, dual-write, backfill, then remove the old column later.', - }, - { - regex: /\bALTER\s+COLUMN\b[\s\S]*\bTYPE\b/i, - message: 'Changing a column type in place can break rolling deployments. Use an additive migration and backfill.', - }, - { - regex: /\bALTER\s+COLUMN\b[\s\S]*\bSET\s+NOT\s+NULL\b/i, - message: 'SET NOT NULL should only happen after a backfill and validation step.', - }, -]; - -function validateMigrationSql(sql, migrationName) { - const errors = []; - const warnings = []; - - for (const pattern of breakingPatterns) { - if (pattern.regex.test(sql) && !sql.includes(BREAKING_CHANGE_MARKER)) { - errors.push(`${migrationName}: ${pattern.message}`); - } - } - - if (/\bCREATE\s+(?:UNIQUE\s+)?INDEX\b/i.test(sql) && !/\bCREATE\s+(?:UNIQUE\s+)?INDEX\s+CONCURRENTLY\b/i.test(sql)) { - if (!sql.includes(BLOCKING_INDEX_MARKER)) { - warnings.push( - `${migrationName}: CREATE INDEX without CONCURRENTLY can block writes on large tables. Review zero-downtime impact.`, - ); - } - } - - return { errors, warnings }; -} - -function validateMigrations(repoRoot = process.cwd()) { - const migrationsDir = path.join(repoRoot, 'prisma', 'migrations'); - const result = { - checkedMigrations: [], - errors: [], - warnings: [], - }; - - if (!fs.existsSync(migrationsDir)) { - result.errors.push(`Migrations directory not found: ${migrationsDir}`); - return result; - } - - const migrationDirs = fs - .readdirSync(migrationsDir, { withFileTypes: true }) - .filter(entry => entry.isDirectory()) - .map(entry => entry.name) - .sort(); - - for (const migrationName of migrationDirs) { - const migrationPath = path.join(migrationsDir, migrationName); - const migrationSqlPath = path.join(migrationPath, 'migration.sql'); - const rollbackSqlPath = path.join(migrationPath, 'rollback.sql'); - - if (!fs.existsSync(migrationSqlPath)) { - result.errors.push(`${migrationName}: missing migration.sql`); - continue; - } - - if (!fs.existsSync(rollbackSqlPath)) { - result.errors.push(`${migrationName}: missing rollback.sql`); - } - - const sql = fs.readFileSync(migrationSqlPath, 'utf8'); - const validation = validateMigrationSql(sql, migrationName); - - result.checkedMigrations.push(migrationName); - result.errors.push(...validation.errors); - result.warnings.push(...validation.warnings); - } - - return result; -} - -function printResult(result) { - console.log(`Checked ${result.checkedMigrations.length} migration(s).`); - - if (result.warnings.length > 0) { - console.log('\nWarnings:'); - for (const warning of result.warnings) { - console.log(`- ${warning}`); - } - } - - if (result.errors.length > 0) { - console.error('\nErrors:'); - for (const error of result.errors) { - console.error(`- ${error}`); - } - } else { - console.log('\nMigration validation passed.'); - } -} - -if (require.main === module) { - const result = validateMigrations(process.cwd()); - printResult(result); - process.exit(result.errors.length > 0 ? 1 : 0); -} - -module.exports = { - validateMigrations, -}; diff --git a/src/analytics/EventAggregator.ts b/src/analytics/EventAggregator.ts deleted file mode 100644 index ae680976..00000000 --- a/src/analytics/EventAggregator.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { AnalyticsEvent } from './StreamProcessor'; - -export interface AggregatedEventStats { - totalEvents: number; - byType: Record; - lastEventAt: number | null; - windowCounts: Record; -} - -@Injectable() -export class EventAggregator { - private readonly logger = new Logger(EventAggregator.name); - private stats: AggregatedEventStats = { - totalEvents: 0, - byType: {}, - lastEventAt: null, - windowCounts: {}, - }; - - ingest(event: AnalyticsEvent): void { - if (!event || !event.eventType) { - this.logger.warn('Ignored invalid event'); - return; - } - - this.stats.totalEvents += 1; - this.stats.byType[event.eventType] = (this.stats.byType[event.eventType] ?? 0) + 1; - this.stats.lastEventAt = event.timestamp; - - const windowKey = this.windowKey(event.timestamp); - this.stats.windowCounts[windowKey] = (this.stats.windowCounts[windowKey] ?? 0) + 1; - - this.logger.debug(`Aggregated event type ${event.eventType} at window ${windowKey}`); - } - - getSnapshot(): AggregatedEventStats { - return JSON.parse(JSON.stringify(this.stats)); - } - - reset(): void { - this.stats = { - totalEvents: 0, - byType: {}, - lastEventAt: null, - windowCounts: {}, - }; - this.logger.log('EventAggregator reset'); - } - - private windowKey(timestamp: number): string { - const date = new Date(timestamp); - const hour = date.getUTCHours().toString().padStart(2, '0'); - const minute = date.getUTCMinutes().toString().padStart(2, '0'); - return `${date.getUTCFullYear()}-${date.getUTCMonth() + 1}-${date.getUTCDate()}T${hour}:${minute}`; - } -} diff --git a/src/analytics/MetricsCalculator.ts b/src/analytics/MetricsCalculator.ts deleted file mode 100644 index f939f8b3..00000000 --- a/src/analytics/MetricsCalculator.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { AnalyticsEvent } from './StreamProcessor'; -import { AggregatedEventStats } from './EventAggregator'; - -export interface MetricDefinition { - metricId: string; - description?: string; - formula: (event: AnalyticsEvent, snapshot: AggregatedEventStats) => number; -} - -export interface CalculatedMetrics { - [metricId: string]: number; -} - -@Injectable() -export class MetricsCalculator { - private readonly logger = new Logger(MetricsCalculator.name); - private metricDefinitions: Record = {}; - private metricValues: CalculatedMetrics = {}; - - defineMetric(metric: MetricDefinition): void { - this.metricDefinitions[metric.metricId] = metric; - this.metricValues[metric.metricId] = 0; - this.logger.log(`Metric defined: ${metric.metricId}`); - } - - removeMetric(metricId: string): void { - delete this.metricDefinitions[metricId]; - delete this.metricValues[metricId]; - this.logger.log(`Metric removed: ${metricId}`); - } - - updateMetrics(event: AnalyticsEvent, snapshot: AggregatedEventStats): void { - for (const metric of Object.values(this.metricDefinitions)) { - const value = metric.formula(event, snapshot); - this.metricValues[metric.metricId] = value; - this.logger.debug(`Metric updated: ${metric.metricId} = ${value}`); - } - } - - getMetrics(): CalculatedMetrics { - return { ...this.metricValues }; - } - - getMetric(metricId: string): number | undefined { - return this.metricValues[metricId]; - } - - reset(): void { - this.metricValues = {}; - Object.keys(this.metricDefinitions).forEach(id => { - this.metricValues[id] = 0; - }); - this.logger.log('MetricsCalculator reset'); - } -} diff --git a/src/analytics/StreamProcessor.ts b/src/analytics/StreamProcessor.ts deleted file mode 100644 index f53a3e32..00000000 --- a/src/analytics/StreamProcessor.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { EventAggregator } from './EventAggregator'; -import { MetricsCalculator } from './MetricsCalculator'; - -export interface AnalyticsEvent { - eventId: string; - eventType: string; - timestamp: number; - payload: Record; - metadata?: Record; -} - -@Injectable() -export class StreamProcessor { - private readonly logger = new Logger(StreamProcessor.name); - private isRunning = false; - - constructor( - private readonly aggregator: EventAggregator, - private readonly metricsCalculator: MetricsCalculator, - ) {} - - start(): void { - if (this.isRunning) { - this.logger.warn('StreamProcessor already running'); - return; - } - - this.isRunning = true; - this.logger.log('StreamProcessor started'); - } - - stop(): void { - this.isRunning = false; - this.logger.log('StreamProcessor stopped'); - } - - async processEvent(event: AnalyticsEvent): Promise { - if (!this.isRunning) { - this.logger.warn('StreamProcessor is not running, starting now'); - this.start(); - } - - this.logger.debug(`Processing event ${event.eventId}:${event.eventType}`); - - try { - this.aggregator.ingest(event); - this.metricsCalculator.updateMetrics(event, this.aggregator.getSnapshot()); - } catch (error) { - this.logger.error( - `Failed to process event ${event.eventId}`, - error instanceof Error ? error.stack : String(error), - ); - throw error; - } - } - - async processBatch(events: AnalyticsEvent[]): Promise { - for (const event of events) { - await this.processEvent(event); - } - } -} diff --git a/src/analytics/analytics.module.ts b/src/analytics/analytics.module.ts deleted file mode 100644 index 05e07534..00000000 --- a/src/analytics/analytics.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Module } from '@nestjs/common'; -import { EventAggregator } from './EventAggregator'; -import { MetricsCalculator } from './MetricsCalculator'; -import { StreamProcessor } from './StreamProcessor'; -import { AnalyticsService } from '../services/AnalyticsService'; - -@Module({ - providers: [EventAggregator, MetricsCalculator, StreamProcessor, AnalyticsService], - exports: [AnalyticsService, EventAggregator, MetricsCalculator], -}) -export class AnalyticsModule {} diff --git a/src/api-keys/README.md b/src/api-keys/README.md deleted file mode 100644 index 58876208..00000000 --- a/src/api-keys/README.md +++ /dev/null @@ -1,368 +0,0 @@ -# API Key Authentication System - -## Overview - -The API Key authentication system provides secure authentication for external services and integrations. API keys are encrypted at rest, have configurable rate limits, and support scope-based permissions. - -## Features - -- ✅ **Secure Storage**: Keys encrypted using AES encryption with `ENCRYPTION_KEY` -- ✅ **One-time Display**: Full API key shown only once at creation -- ✅ **Scope-based Permissions**: Control access to specific resources -- ✅ **Rate Limiting**: Configurable per-key or global rate limits (requests per minute) -- ✅ **Usage Tracking**: Track request count and last used timestamp -- ✅ **Revocation**: Soft-delete keys to deactivate them - -## API Key Format - -``` -propchain_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -``` - -- **Prefix**: `propchain_live_` (environment identifier) -- **Length**: 32 random characters after prefix -- **Total**: 48 characters - -## Available Scopes - -```typescript -- read:properties - Read access to property data -- write:properties - Create/update property data -- read:transactions - Read access to transaction data -``` - -## API Endpoints - -### Create API Key - -```http -POST /api-keys -Authorization: Bearer -Content-Type: application/json - -{ - "name": "Production Integration Key", - "scopes": ["read:properties", "write:properties"], - "rateLimit": 100 // Optional, defaults to global limit -} -``` - -**Response** (201 Created): - -```json -{ - "id": "cly1234567890", - "name": "Production Integration Key", - "key": "propchain_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6", - "keyPrefix": "propchain_live_a1b2c3d4", - "scopes": ["read:properties", "write:properties"], - "requestCount": "0", - "lastUsedAt": null, - "isActive": true, - "rateLimit": 100, - "createdAt": "2026-01-22T10:00:00.000Z", - "updatedAt": "2026-01-22T10:00:00.000Z" -} -``` - -⚠️ **Important**: Save the full `key` value immediately - it will never be shown again! - -### List API Keys - -```http -GET /api-keys -Authorization: Bearer -``` - -**Response** (200 OK): - -```json -[ - { - "id": "cly1234567890", - "name": "Production Integration Key", - "keyPrefix": "propchain_live_a1b2c3d4", - "scopes": ["read:properties", "write:properties"], - "requestCount": "12345", - "lastUsedAt": "2026-01-22T15:30:00.000Z", - "isActive": true, - "rateLimit": 100, - "createdAt": "2026-01-22T10:00:00.000Z", - "updatedAt": "2026-01-22T10:00:00.000Z" - } -] -``` - -### Get API Key Details - -```http -GET /api-keys/:id -Authorization: Bearer -``` - -### Update API Key - -```http -PATCH /api-keys/:id -Authorization: Bearer -Content-Type: application/json - -{ - "name": "Updated Key Name", - "scopes": ["read:properties"], - "rateLimit": 200 -} -``` - -### Revoke API Key - -```http -DELETE /api-keys/:id -Authorization: Bearer -``` - -**Response**: 204 No Content - -## Using API Keys - -### Option 1: Authorization Header - -```http -GET /properties -Authorization: Bearer propchain_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 -``` - -### Option 2: X-API-Key Header - -```http -GET /properties -X-API-Key: propchain_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 -``` - -## Protecting Routes with API Keys - -### Using the API Key Guard - -```typescript -import { Controller, Get, UseGuards } from '@nestjs/common'; -import { ApiKeyGuard } from '../common/guards/api-key.guard'; -import { RequireScopes } from '../common/decorators/require-scopes.decorator'; -import { ApiKey } from '../common/decorators/api-key.decorator'; - -@Controller('properties') -@UseGuards(ApiKeyGuard) -export class PropertiesController { - @Get() - @RequireScopes('read:properties') - async findAll(@ApiKey() apiKey: any) { - // apiKey contains: { id, name, scopes, rateLimit } - console.log(`Request from API key: ${apiKey.name}`); - // Your logic here - } - - @Post() - @RequireScopes('write:properties') - async create(@ApiKey() apiKey: any, @Body() createDto: any) { - // Only keys with 'write:properties' scope can access this - } -} -``` - -### Protecting Specific Endpoints - -```typescript -import { Controller, Get, UseGuards } from '@nestjs/common'; -import { ApiKeyGuard } from '../common/guards/api-key.guard'; -import { RequireScopes } from '../common/decorators/require-scopes.decorator'; - -@Controller('external-api') -export class ExternalApiController { - // This endpoint requires API key with read:properties scope - @Get('properties') - @UseGuards(ApiKeyGuard) - @RequireScopes('read:properties') - async getProperties() { - return { data: 'properties' }; - } - - // This endpoint requires multiple scopes - @Post('properties') - @UseGuards(ApiKeyGuard) - @RequireScopes('read:properties', 'write:properties') - async createProperty() { - return { success: true }; - } -} -``` - -## Rate Limiting - -### Global Rate Limit - -Set in environment variables: - -```env -API_KEY_RATE_LIMIT_PER_MINUTE=60 -``` - -### Per-Key Rate Limit - -Specify when creating or updating an API key: - -```json -{ - "name": "High Volume Integration", - "scopes": ["read:properties"], - "rateLimit": 1000 -} -``` - -Rate limits are enforced using Redis with a sliding window of 1 minute. - -### Rate Limit Errors - -When rate limit is exceeded: - -```json -{ - "statusCode": 401, - "message": "Rate limit exceeded" -} -``` - -## Security Best Practices - -1. **Store Securely**: Save API keys in environment variables or secure vaults, never in code -2. **Use HTTPS**: Always use HTTPS in production to protect keys in transit -3. **Minimum Scopes**: Grant only the minimum required scopes -4. **Rotate Regularly**: Create new keys and revoke old ones periodically -5. **Monitor Usage**: Check `requestCount` and `lastUsedAt` to detect anomalies -6. **Set Rate Limits**: Configure appropriate rate limits for each integration - -## Environment Variables - -Add to your `.env` file: - -```env -# Required for encryption -ENCRYPTION_KEY=your-32-character-encryption-key-here - -# Optional rate limit configuration -API_KEY_RATE_LIMIT_PER_MINUTE=60 -``` - -⚠️ **Important**: `ENCRYPTION_KEY` must be exactly 32 characters for AES-256 encryption. - -## Example Integration - -### Node.js/JavaScript - -```javascript -const axios = require('axios'); - -const API_KEY = 'propchain_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6'; -const BASE_URL = 'https://api.propchain.io'; - -// Using Authorization header -const response = await axios.get(`${BASE_URL}/properties`, { - headers: { - Authorization: `Bearer ${API_KEY}`, - }, -}); - -// Or using X-API-Key header -const response = await axios.get(`${BASE_URL}/properties`, { - headers: { - 'X-API-Key': API_KEY, - }, -}); -``` - -### Python - -```python -import requests - -API_KEY = 'propchain_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6' -BASE_URL = 'https://api.propchain.io' - -# Using Authorization header -response = requests.get( - f'{BASE_URL}/properties', - headers={'Authorization': f'Bearer {API_KEY}'} -) - -# Or using X-API-Key header -response = requests.get( - f'{BASE_URL}/properties', - headers={'X-API-Key': API_KEY} -) -``` - -### cURL - -```bash -# Using Authorization header -curl -H "Authorization: Bearer propchain_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" \ - https://api.propchain.io/properties - -# Using X-API-Key header -curl -H "X-API-Key: propchain_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" \ - https://api.propchain.io/properties -``` - -## Troubleshooting - -### "Invalid API key format" - -- Ensure the key starts with `propchain_live_` -- Check for extra spaces or line breaks - -### "Invalid or revoked API key" - -- Key might be revoked - check with `GET /api-keys/:id` -- Key might be from a different environment - -### "Insufficient permissions" - -- Check that the API key has the required scopes -- Update scopes with `PATCH /api-keys/:id` - -### "Rate limit exceeded" - -- Wait 1 minute for the rate limit window to reset -- Or increase the rate limit for the key - -## Testing - -Run unit tests: - -```bash -npm run test -- api-key.service.spec.ts -``` - -Run e2e tests: - -```bash -npm run test:e2e -- api-keys.e2e-spec.ts -``` - -## Database Schema - -```prisma -model ApiKey { - id String @id @default(cuid()) - name String - key String @unique - keyPrefix String @map("key_prefix") - scopes String[] - requestCount BigInt @default(0) @map("request_count") - lastUsedAt DateTime? @map("last_used_at") - isActive Boolean @default(true) @map("is_active") - rateLimit Int? @map("rate_limit") - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - - @@map("api_keys") -} -``` diff --git a/src/api-keys/SETUP.md b/src/api-keys/SETUP.md deleted file mode 100644 index 5831c501..00000000 --- a/src/api-keys/SETUP.md +++ /dev/null @@ -1,249 +0,0 @@ -# API Key System - Setup Checklist - -Follow these steps to complete the API key authentication setup: - -## ✅ Prerequisites - -- [x] Prisma schema updated with ApiKey model -- [x] API key service, controller, and guard created -- [x] Module integrated into AppModule -- [x] Unit and integration tests created - -## 🚀 Required Steps - -### 1. Set Environment Variable - -Add to your `.env` file (create if it doesn't exist): - -```bash -# Must be at least 32 characters long -ENCRYPTION_KEY=your-secure-32-character-encryption-key-here-minimum -``` - -**Generate a secure key:** - -```bash -# Option 1: Using Node.js -node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" - -# Option 2: Using OpenSSL -openssl rand -hex 32 - -# Option 3: Using Python -python3 -c "import secrets; print(secrets.token_hex(32))" -``` - -### 2. Run Database Migration - -Create and apply the migration for the `api_keys` table: - -```bash -# Create migration -npx prisma migrate dev --name add_api_keys - -# Or if migration already exists -npx prisma migrate dev -``` - -### 3. Generate Prisma Client - -Update the Prisma client with the new ApiKey model: - -```bash -npx prisma generate -``` - -### 4. Verify Installation - -Check that everything is working: - -```bash -# Run unit tests -npm run test -- api-key.service.spec.ts - -# Run integration tests (requires database) -npm run test:e2e -- api-key.e2e-spec.ts - -# Start the application -npm run start:dev -``` - -### 5. Create Your First API Key - -Once the server is running: - -1. **Register/Login** to get a JWT token: - -```bash -curl -X POST http://localhost:3000/auth/login \ - -H "Content-Type: application/json" \ - -d '{"email": "admin@example.com", "password": "your-password"}' -``` - -2. **Create an API key**: - -```bash -curl -X POST http://localhost:3000/api-keys \ - -H "Authorization: Bearer YOUR_JWT_TOKEN" \ - -H "Content-Type: application/json" \ - -d '{ - "name": "Test Integration", - "description": "Testing API keys", - "scopes": ["read:properties", "write:properties"], - "rateLimit": 60 - }' -``` - -3. **Save the returned API key** - it will only be shown once! - -### 6. Test API Key Authentication - -Test the API key works: - -```bash -# Using X-API-Key header -curl -H "X-API-Key: propchain_test_YOUR_KEY" \ - http://localhost:3000/health - -# Using Authorization header -curl -H "Authorization: Bearer propchain_test_YOUR_KEY" \ - http://localhost:3000/health -``` - -## 📝 Next Steps - -### Protect Your Routes - -Apply the API key guard to routes that should accept API key authentication: - -```typescript -import { UseGuards } from '@nestjs/common'; -import { ApiKeyGuard } from '../common/guards/api-key.guard'; -import { ApiKeyScopes } from '../common/decorators/api-key-scopes.decorator'; - -@Controller('your-resource') -export class YourController { - @Get() - @UseGuards(ApiKeyGuard) - @ApiKeyScopes('read:properties') - yourMethod() { - // Protected with API key - } -} -``` - -See `src/api-keys/examples/properties-with-api-keys.example.ts` for detailed examples. - -### Add Custom Scopes - -To add new scopes for your specific use case: - -1. Define scope constants (optional but recommended): - -```typescript -// src/api-keys/constants/scopes.ts -export const API_KEY_SCOPES = { - // Properties - READ_PROPERTIES: 'read:properties', - WRITE_PROPERTIES: 'write:properties', - - // Transactions - READ_TRANSACTIONS: 'read:transactions', - WRITE_TRANSACTIONS: 'write:transactions', - - // Add your custom scopes here - READ_ANALYTICS: 'read:analytics', - ADMIN_ACCESS: 'admin:all', -} as const; -``` - -2. Use the scopes in your controllers: - -```typescript -@ApiKeyScopes(API_KEY_SCOPES.READ_ANALYTICS) -``` - -### Configure Swagger/OpenAPI - -The API key endpoints are already documented with Swagger. To add API key authentication to Swagger UI, update your `main.ts`: - -```typescript -const config = new DocumentBuilder() - .setTitle('PropChain API') - .addBearerAuth() - .addApiKey({ type: 'apiKey', name: 'X-API-Key', in: 'header' }, 'X-API-Key') - .build(); -``` - -## 🔒 Security Checklist - -- [ ] `ENCRYPTION_KEY` is set and at least 32 characters -- [ ] `ENCRYPTION_KEY` is not committed to version control -- [ ] Production uses `propchain_live_` prefix (NODE_ENV=production) -- [ ] Test environment uses `propchain_test_` prefix -- [ ] Rate limits are configured appropriately -- [ ] Minimum necessary scopes are granted to each key -- [ ] API keys are stored securely by clients -- [ ] Monitoring is in place for suspicious usage patterns - -## 📊 Monitoring - -Track API key usage: - -```bash -# List all API keys with usage statistics -curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \ - http://localhost:3000/api-keys -``` - -Check the response for: - -- `requestCount` - Total requests made -- `lastUsedAt` - Last time the key was used -- `isActive` - Whether the key is still active - -## 🐛 Troubleshooting - -### Migration Issues - -If migration fails: - -```bash -# Reset database (⚠️ WARNING: This deletes all data) -npx prisma migrate reset - -# Or manually create migration -npx prisma migrate dev --create-only --name add_api_keys -# Then edit the migration file if needed -npx prisma migrate dev -``` - -### Encryption Errors - -If you see "ENCRYPTION_KEY must be at least 32 characters": - -```bash -# Verify your .env file has the key -cat .env | grep ENCRYPTION_KEY - -# Generate a new one if needed -node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" -``` - -### Rate Limiting Issues - -If requests are being rate limited unexpectedly: - -- Current implementation is simple (checks lastUsedAt within 1 minute) -- For production, consider implementing Redis-based rate limiting -- See `RedisService` for integration - -## 📚 Resources - -- [README.md](./README.md) - Full documentation -- [examples/](./examples/) - Code examples -- [Test files](../../test/api-keys/) - Test examples - -## ✅ Setup Complete! - -Once all steps are completed, your API key authentication system is ready to use! 🎉 diff --git a/src/api-keys/api-key-analytics.service.ts b/src/api-keys/api-key-analytics.service.ts deleted file mode 100644 index a7c391ef..00000000 --- a/src/api-keys/api-key-analytics.service.ts +++ /dev/null @@ -1,281 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { PrismaService } from '../database/prisma/prisma.service'; - -export interface UsageLogEntry { - apiKeyId: string; - endpoint: string; - method: string; - statusCode: number; - responseTime: number; - ipAddress?: string; - userAgent?: string; -} - -export interface ApiKeyAnalyticsSummary { - totalRequests: number; - uniqueEndpoints: number; - averageResponseTime: number; - errorRate: number; - topEndpoints: EndpointUsage[]; - requestsByDay: DailyRequestCount[]; - requestsByHour: HourlyRequestCount[]; -} - -export interface EndpointUsage { - endpoint: string; - method: string; - count: number; - averageResponseTime: number; - errorCount: number; -} - -export interface DailyRequestCount { - date: string; - count: number; -} - -export interface HourlyRequestCount { - hour: number; - count: number; -} - -export interface ApiKeyUsageReport { - apiKeyId: string; - apiKeyName: string; - period: { - start: Date; - end: Date; - }; - summary: ApiKeyAnalyticsSummary; -} - -@Injectable() -export class ApiKeyAnalyticsService { - private readonly logger = new Logger(ApiKeyAnalyticsService.name); - - constructor(private readonly prisma: PrismaService) {} - - /** - * Log an API key usage event - */ - async logUsage(entry: UsageLogEntry): Promise { - try { - await this.prisma.apiKeyUsageLog.create({ - data: { - apiKeyId: entry.apiKeyId, - endpoint: entry.endpoint, - method: entry.method, - statusCode: entry.statusCode, - responseTime: entry.responseTime, - ipAddress: entry.ipAddress, - userAgent: entry.userAgent, - }, - }); - } catch (error) { - this.logger.error(`Failed to log API key usage: ${error.message}`); - // Don't throw - usage logging should not break the request - } - } - - /** - * Get analytics summary for a specific API key - */ - async getAnalyticsSummary(apiKeyId: string, startDate: Date, endDate: Date): Promise { - const logs = await this.prisma.apiKeyUsageLog.findMany({ - where: { - apiKeyId, - createdAt: { - gte: startDate, - lte: endDate, - }, - }, - select: { - endpoint: true, - method: true, - statusCode: true, - responseTime: true, - createdAt: true, - }, - }); - - const totalRequests = logs.length; - const errorCount = logs.filter(l => l.statusCode >= 400).length; - const totalResponseTime = logs.reduce((sum, l) => sum + l.responseTime, 0); - - // Group by endpoint - const endpointMap = new Map(); - for (const log of logs) { - const key = `${log.method} ${log.endpoint}`; - const existing = endpointMap.get(key) || { count: 0, responseTime: 0, errors: 0 }; - existing.count++; - existing.responseTime += log.responseTime; - if (log.statusCode >= 400) { - existing.errors++; - } - endpointMap.set(key, existing); - } - - const topEndpoints: EndpointUsage[] = Array.from(endpointMap.entries()) - .map(([key, data]) => { - const [method, endpoint] = key.split(' ', 2); - return { - endpoint, - method, - count: data.count, - averageResponseTime: Math.round(data.responseTime / data.count), - errorCount: data.errors, - }; - }) - .sort((a, b) => b.count - a.count) - .slice(0, 10); - - // Group by day - const dayMap = new Map(); - for (const log of logs) { - const day = log.createdAt.toISOString().split('T')[0]; - dayMap.set(day, (dayMap.get(day) || 0) + 1); - } - - const requestsByDay: DailyRequestCount[] = Array.from(dayMap.entries()) - .map(([date, count]) => ({ date, count })) - .sort((a, b) => a.date.localeCompare(b.date)); - - // Group by hour - const hourMap = new Map(); - for (const log of logs) { - const hour = log.createdAt.getHours(); - hourMap.set(hour, (hourMap.get(hour) || 0) + 1); - } - - const requestsByHour: HourlyRequestCount[] = Array.from(hourMap.entries()) - .map(([hour, count]) => ({ hour, count })) - .sort((a, b) => a.hour - b.hour); - - return { - totalRequests, - uniqueEndpoints: endpointMap.size, - averageResponseTime: totalRequests > 0 ? Math.round(totalResponseTime / totalRequests) : 0, - errorRate: totalRequests > 0 ? Math.round((errorCount / totalRequests) * 100) : 0, - topEndpoints, - requestsByDay, - requestsByHour, - }; - } - - /** - * Get a full usage report for an API key - */ - async getUsageReport(apiKeyId: string, startDate: Date, endDate: Date): Promise { - const apiKey = await this.prisma.apiKey.findUnique({ - where: { id: apiKeyId }, - select: { id: true, name: true }, - }); - - if (!apiKey) { - throw new Error(`API key with ID ${apiKeyId} not found`); - } - - const summary = await this.getAnalyticsSummary(apiKeyId, startDate, endDate); - - return { - apiKeyId: apiKey.id, - apiKeyName: apiKey.name, - period: { start: startDate, end: endDate }, - summary, - }; - } - - /** - * Get analytics for all API keys (admin view) - */ - async getAllKeysAnalytics(startDate: Date, endDate: Date): Promise { - const apiKeys = await this.prisma.apiKey.findMany({ - select: { id: true, name: true }, - }); - - const reports: ApiKeyUsageReport[] = []; - for (const apiKey of apiKeys) { - const summary = await this.getAnalyticsSummary(apiKey.id, startDate, endDate); - if (summary.totalRequests > 0) { - reports.push({ - apiKeyId: apiKey.id, - apiKeyName: apiKey.name, - period: { start: startDate, end: endDate }, - summary, - }); - } - } - - return reports.sort((a, b) => b.summary.totalRequests - a.summary.totalRequests); - } - - /** - * Clean up old usage logs (data retention) - */ - async cleanupOldLogs(retentionDays: number): Promise { - const cutoffDate = new Date(); - cutoffDate.setDate(cutoffDate.getDate() - retentionDays); - - const result = await this.prisma.apiKeyUsageLog.deleteMany({ - where: { - createdAt: { lt: cutoffDate }, - }, - }); - - this.logger.log(`Cleaned up ${result.count} old API key usage logs`); - return result.count; - } - - /** - * Get usage statistics for a specific endpoint - */ - async getEndpointStats( - endpoint: string, - startDate: Date, - endDate: Date, - ): Promise<{ - totalRequests: number; - averageResponseTime: number; - errorRate: number; - topApiKeys: { apiKeyId: string; apiKeyName: string; count: number }[]; - }> { - const logs = await this.prisma.apiKeyUsageLog.findMany({ - where: { - endpoint, - createdAt: { - gte: startDate, - lte: endDate, - }, - }, - include: { - apiKey: { - select: { id: true, name: true }, - }, - }, - }); - - const totalRequests = logs.length; - const errorCount = logs.filter(l => l.statusCode >= 400).length; - const totalResponseTime = logs.reduce((sum, l) => sum + l.responseTime, 0); - - // Group by API key - const keyMap = new Map(); - for (const log of logs) { - const existing = keyMap.get(log.apiKeyId) || { name: log.apiKey.name, count: 0 }; - existing.count++; - keyMap.set(log.apiKeyId, existing); - } - - const topApiKeys = Array.from(keyMap.entries()) - .map(([apiKeyId, data]) => ({ apiKeyId, apiKeyName: data.name, count: data.count })) - .sort((a, b) => b.count - a.count) - .slice(0, 10); - - return { - totalRequests, - averageResponseTime: totalRequests > 0 ? Math.round(totalResponseTime / totalRequests) : 0, - errorRate: totalRequests > 0 ? Math.round((errorCount / totalRequests) * 100) : 0, - topApiKeys, - }; - } -} diff --git a/src/api-keys/api-key-rotation.scheduler.ts b/src/api-keys/api-key-rotation.scheduler.ts deleted file mode 100644 index f5d7418c..00000000 --- a/src/api-keys/api-key-rotation.scheduler.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { Cron, CronExpression } from '@nestjs/schedule'; -import { ApiKeyService } from './api-key.service'; -import { ApiKeyAnalyticsService } from './api-key-analytics.service'; -import { ConfigService } from '@nestjs/config'; -import { BackgroundJobMonitoringService } from '../communication/jobs/background-job-monitoring.service'; - -@Injectable() -export class ApiKeyRotationScheduler { - private readonly logger = new Logger(ApiKeyRotationScheduler.name); - private readonly retentionDays: number; - - constructor( - private readonly apiKeyService: ApiKeyService, - private readonly analyticsService: ApiKeyAnalyticsService, - private readonly configService: ConfigService, - private readonly jobMonitoringService: BackgroundJobMonitoringService, - ) { - this.retentionDays = this.configService.get('API_KEY_LOG_RETENTION_DAYS', 90); - } - - /** - * Check for expired API keys and rotate them automatically - * Runs daily at midnight - */ - @Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT) - async handleAutomaticRotation(): Promise { - this.logger.log('Starting automatic API key rotation check...'); - - try { - const results = await this.apiKeyService.autoRotateExpiredKeys(); - - if (results.length > 0) { - this.logger.log(`Automatically rotated ${results.length} API key(s)`); - results.forEach(result => { - this.logger.log(` - ${result.name}: ${result.oldKeyPrefix} -> ${result.newKeyPrefix}`); - }); - } else { - this.logger.log('No API keys required automatic rotation'); - } - - await this.jobMonitoringService.recordScheduledExecution('api-key-rotation.auto-rotate', 'success', { - rotatedCount: results.length, - }); - } catch (error) { - this.logger.error(`Automatic rotation failed: ${error.message}`); - await this.jobMonitoringService.recordScheduledExecution('api-key-rotation.auto-rotate', 'failed', { - message: error.message, - }); - } - } - - /** - * Check for keys approaching rotation and log warnings - * Runs daily at 6 AM - */ - @Cron(CronExpression.EVERY_DAY_AT_6AM) - async handleRotationWarnings(): Promise { - this.logger.log('Checking for API keys approaching rotation...'); - - try { - const approachingKeys = await this.apiKeyService.getKeysApproachingRotation(); - - if (approachingKeys.length > 0) { - this.logger.warn(`${approachingKeys.length} API key(s) will require rotation soon:`); - approachingKeys.forEach(key => { - this.logger.warn(` - ${key.name} (${key.keyPrefix}): ${key.daysUntilRotation} days until rotation`); - }); - } else { - this.logger.log('No API keys approaching rotation'); - } - - await this.jobMonitoringService.recordScheduledExecution('api-key-rotation.warning-check', 'success', { - approachingCount: approachingKeys.length, - }); - } catch (error) { - this.logger.error(`Rotation warning check failed: ${error.message}`); - await this.jobMonitoringService.recordScheduledExecution('api-key-rotation.warning-check', 'failed', { - message: error.message, - }); - } - } - - /** - * Clean up old usage logs for data retention compliance - * Runs weekly on Sunday at 2 AM - */ - @Cron(CronExpression.EVERY_WEEK) - async handleLogCleanup(): Promise { - this.logger.log('Starting API key usage log cleanup...'); - - try { - const deletedCount = await this.analyticsService.cleanupOldLogs(this.retentionDays); - this.logger.log(`Cleaned up ${deletedCount} old usage log entries`); - await this.jobMonitoringService.recordScheduledExecution('api-key-rotation.log-cleanup', 'success', { - deletedCount, - }); - } catch (error) { - this.logger.error(`Log cleanup failed: ${error.message}`); - await this.jobMonitoringService.recordScheduledExecution('api-key-rotation.log-cleanup', 'failed', { - message: error.message, - }); - } - } -} diff --git a/src/api-keys/api-key.controller.ts b/src/api-keys/api-key.controller.ts deleted file mode 100644 index 43643e3c..00000000 --- a/src/api-keys/api-key.controller.ts +++ /dev/null @@ -1,215 +0,0 @@ -import { - Controller, - Get, - Post, - Body, - Patch, - Param, - Delete, - UseGuards, - HttpCode, - HttpStatus, - Query, -} from '@nestjs/common'; -import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth, ApiParam, ApiQuery } from '@nestjs/swagger'; -import { ApiKeyService, RotationStatus, RotationResult } from './api-key.service'; -import { CreateApiKeyDto } from './dto/create-api-key.dto'; -import { UpdateApiKeyDto } from './dto/update-api-key.dto'; -import { ApiKeyResponseDto, CreateApiKeyResponseDto } from './dto/api-key-response.dto'; -import { PaginationQueryDto, PaginatedResponseDto } from '../common/pagination'; -import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; - -@ApiTags('API Keys') -@Controller('api-keys') -@UseGuards(JwtAuthGuard) -@ApiBearerAuth() -export class ApiKeyController { - constructor(private readonly apiKeyService: ApiKeyService) {} - - @Post() - @ApiOperation({ - summary: 'Create a new API key', - description: 'Generate a new API key for external service integration. The full key is only shown once.', - }) - @ApiResponse({ - status: 201, - description: 'API key created successfully', - type: CreateApiKeyResponseDto, - }) - @ApiResponse({ status: 400, description: 'Invalid scopes provided' }) - @ApiResponse({ status: 401, description: 'Unauthorized' }) - async create(@Body() createApiKeyDto: CreateApiKeyDto): Promise { - return this.apiKeyService.create(createApiKeyDto); - } - - @Get() - @ApiOperation({ - summary: 'List all API keys', - description: 'Retrieve all API keys with pagination support and partial key display', - }) - @ApiResponse({ - status: 200, - description: 'List of API keys retrieved successfully', - schema: { - properties: { - data: { - type: 'array', - items: { $ref: '#/components/schemas/ApiKeyResponseDto' }, - }, - meta: { - type: 'object', - properties: { - total: { type: 'number' }, - page: { type: 'number' }, - limit: { type: 'number' }, - pages: { type: 'number' }, - hasNext: { type: 'boolean' }, - hasPrev: { type: 'boolean' }, - }, - }, - }, - }, - }) - @ApiResponse({ status: 401, description: 'Unauthorized' }) - async findAll( - @Query() paginationQuery: PaginationQueryDto, - ): Promise> { - return this.apiKeyService.findAll(paginationQuery); - } - - @Get(':id') - @ApiOperation({ - summary: 'Get API key details', - description: 'Retrieve details of a specific API key by ID', - }) - @ApiParam({ name: 'id', description: 'API key ID' }) - @ApiResponse({ - status: 200, - description: 'API key details retrieved successfully', - type: ApiKeyResponseDto, - }) - @ApiResponse({ status: 404, description: 'API key not found' }) - @ApiResponse({ status: 401, description: 'Unauthorized' }) - async findOne(@Param('id') id: string): Promise { - return this.apiKeyService.findOne(id); - } - - @Patch(':id') - @ApiOperation({ - summary: 'Update API key', - description: 'Update API key settings (name, scopes, rate limit)', - }) - @ApiParam({ name: 'id', description: 'API key ID' }) - @ApiResponse({ - status: 200, - description: 'API key updated successfully', - type: ApiKeyResponseDto, - }) - @ApiResponse({ status: 404, description: 'API key not found' }) - @ApiResponse({ status: 400, description: 'Invalid update data' }) - @ApiResponse({ status: 401, description: 'Unauthorized' }) - async update(@Param('id') id: string, @Body() updateApiKeyDto: UpdateApiKeyDto): Promise { - return this.apiKeyService.update(id, updateApiKeyDto); - } - - @Delete(':id') - @HttpCode(HttpStatus.NO_CONTENT) - @ApiOperation({ - summary: 'Revoke API key', - description: 'Revoke (soft delete) an API key, making it inactive', - }) - @ApiParam({ name: 'id', description: 'API key ID' }) - @ApiResponse({ status: 204, description: 'API key revoked successfully' }) - @ApiResponse({ status: 404, description: 'API key not found' }) - @ApiResponse({ status: 401, description: 'Unauthorized' }) - async revoke(@Param('id') id: string): Promise { - return this.apiKeyService.revoke(id); - } - - // ==================== ROTATION ENDPOINTS ==================== - - @Post(':id/rotate') - @ApiOperation({ - summary: 'Rotate API key', - description: 'Generate a new API key and deactivate the old one. The new key is shown only once.', - }) - @ApiParam({ name: 'id', description: 'API key ID' }) - @ApiResponse({ - status: 200, - description: 'API key rotated successfully', - }) - @ApiResponse({ status: 404, description: 'API key not found' }) - @ApiResponse({ status: 400, description: 'Cannot rotate a revoked API key' }) - @ApiResponse({ status: 401, description: 'Unauthorized' }) - async rotateKey(@Param('id') id: string): Promise { - return this.apiKeyService.rotateKey(id); - } - - @Get(':id/rotation-status') - @ApiOperation({ - summary: 'Get rotation status', - description: 'Check if an API key requires rotation and when it was last rotated', - }) - @ApiParam({ name: 'id', description: 'API key ID' }) - @ApiResponse({ - status: 200, - description: 'Rotation status retrieved successfully', - }) - @ApiResponse({ status: 404, description: 'API key not found' }) - @ApiResponse({ status: 401, description: 'Unauthorized' }) - async getRotationStatus(@Param('id') id: string): Promise { - return this.apiKeyService.getRotationStatus(id); - } - - @Get('rotation/required') - @ApiOperation({ - summary: 'Get keys requiring rotation', - description: 'List all API keys that have passed their rotation due date', - }) - @ApiResponse({ - status: 200, - description: 'List of API keys requiring rotation', - }) - @ApiResponse({ status: 401, description: 'Unauthorized' }) - async getKeysRequiringRotation(): Promise { - return this.apiKeyService.getKeysRequiringRotation(); - } - - @Get('rotation/approaching') - @ApiOperation({ - summary: 'Get keys approaching rotation', - description: 'List all API keys that will require rotation within the warning period', - }) - @ApiResponse({ - status: 200, - description: 'List of API keys approaching rotation', - }) - @ApiResponse({ status: 401, description: 'Unauthorized' }) - async getKeysApproachingRotation(): Promise { - return this.apiKeyService.getKeysApproachingRotation(); - } - - // ==================== ANALYTICS ENDPOINTS ==================== - - @Get(':id/analytics') - @ApiOperation({ - summary: 'Get API key usage analytics', - description: 'Retrieve detailed usage analytics for a specific API key', - }) - @ApiParam({ name: 'id', description: 'API key ID' }) - @ApiQuery({ name: 'startDate', description: 'Start date (ISO 8601)', example: '2026-01-01T00:00:00Z' }) - @ApiQuery({ name: 'endDate', description: 'End date (ISO 8601)', example: '2026-01-31T23:59:59Z' }) - @ApiResponse({ - status: 200, - description: 'Usage analytics retrieved successfully', - }) - @ApiResponse({ status: 404, description: 'API key not found' }) - @ApiResponse({ status: 401, description: 'Unauthorized' }) - async getUsageAnalytics( - @Param('id') id: string, - @Query('startDate') startDate: string, - @Query('endDate') endDate: string, - ) { - return this.apiKeyService.getUsageAnalytics(id, new Date(startDate), new Date(endDate)); - } -} diff --git a/src/api-keys/api-key.module.ts b/src/api-keys/api-key.module.ts deleted file mode 100644 index a67e29e7..00000000 --- a/src/api-keys/api-key.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Module } from '@nestjs/common'; -import { ApiKeyService } from './api-key.service'; -import { ApiKeyController } from './api-key.controller'; -import { PrismaModule } from '../database/prisma/prisma.module'; - -@Module({ - imports: [PrismaModule], - controllers: [ApiKeyController], - providers: [ApiKeyService], - exports: [ApiKeyService], -}) -export class ApiKeyModule {} diff --git a/src/api-keys/api-key.service.ts b/src/api-keys/api-key.service.ts deleted file mode 100644 index 59321b95..00000000 --- a/src/api-keys/api-key.service.ts +++ /dev/null @@ -1,535 +0,0 @@ -import { Injectable, NotFoundException, BadRequestException, UnauthorizedException } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; -import { PrismaService } from '../database/prisma/prisma.service'; -import { RedisService } from '../common/services/redis.service'; -import { PaginationService, PaginationQueryDto, PaginatedResponseDto } from '../common/pagination'; -import { CreateApiKeyDto } from './dto/create-api-key.dto'; -import { UpdateApiKeyDto } from './dto/update-api-key.dto'; -import { ApiKeyResponseDto, CreateApiKeyResponseDto } from './dto/api-key-response.dto'; -import { API_KEY_SCOPES, ApiKeyScope } from './enums/api-key-scope.enum'; -import { ApiKeyAnalyticsService, UsageLogEntry } from './api-key-analytics.service'; -import * as crypto from 'crypto'; -import * as CryptoJS from 'crypto-js'; -import { BaseService } from '../common/services/base.service'; -import { BoundaryValidationService } from '../common/validation'; - -export interface RotationResult { - id: string; - name: string; - oldKeyPrefix: string; - newKeyPrefix: string; - key: string; // New plain key (shown only once) - rotatedAt: Date; -} - -export interface RotationStatus { - id: string; - name: string; - keyPrefix: string; - lastRotatedAt?: Date; - rotationDueAt?: Date; - daysUntilRotation?: number; - requiresRotation: boolean; -} - -@Injectable() -export class ApiKeyService extends BaseService { - private readonly encryptionKey: string; - private readonly globalRateLimit: number; - private readonly rotationIntervalDays: number; - private readonly rotationWarningDays: number; - - constructor( - private readonly prisma: PrismaService, - private readonly redis: RedisService, - private readonly configService: ConfigService, - private readonly paginationService: PaginationService, - private readonly analyticsService: ApiKeyAnalyticsService, - boundaryValidation: BoundaryValidationService, - ) { - super(boundaryValidation, ApiKeyService.name); - this.encryptionKey = this.configService.get('ENCRYPTION_KEY'); - this.globalRateLimit = this.configService.get('API_KEY_RATE_LIMIT_PER_MINUTE', 60); - this.rotationIntervalDays = this.configService.get('API_KEY_ROTATION_DAYS', 90); - this.rotationWarningDays = this.configService.get('API_KEY_ROTATION_WARNING_DAYS', 7); - - if (!this.encryptionKey) { - throw new Error('ENCRYPTION_KEY must be set in environment variables'); - } - } - - async create(createApiKeyDto: CreateApiKeyDto): Promise { - const input = await this.validateInput(CreateApiKeyDto, createApiKeyDto, 'create'); - this.validateScopes(input.scopes); - - const plainKey = this.generateApiKey(); - const keyPrefix = this.extractKeyPrefix(plainKey); - const encryptedKey = this.encryptKey(plainKey); - - // Set rotation due date - const rotationDueAt = new Date(); - rotationDueAt.setDate(rotationDueAt.getDate() + this.rotationIntervalDays); - - const apiKey = await this.prisma.executeWithTimeout( - this.prisma.apiKey.create({ - data: { - name: input.name, - key: encryptedKey, - keyPrefix, - scopes: input.scopes, - rateLimit: input.rateLimit, - rotationDueAt, - lastRotatedAt: new Date(), - }, - }), - 5000 // 5 second timeout for API key creation - ); - - return this.mapOutput(CreateApiKeyResponseDto, { - ...this.mapToResponseDto(apiKey), - key: plainKey, - }); - } - - async findAll( - paginationQuery?: PaginationQueryDto, - ): Promise> { - const normalizedQuery = paginationQuery - ? await this.validateInput(PaginationQueryDto, paginationQuery, 'findAll', { skipMissingProperties: true }) - : undefined; - - // If no pagination query provided, return all (for backward compatibility) - if (!normalizedQuery) { - const apiKeys = await this.prisma.executeWithTimeout( - this.prisma.apiKey.findMany({ - orderBy: { createdAt: 'desc' }, - }), - 10000 // 10 second timeout for large queries - ); - return apiKeys.map(apiKey => this.mapToResponseDto(apiKey)); - } - - // Paginated response - const { skip, take, orderBy } = this.paginationService.getPrismaOptions(normalizedQuery, 'createdAt'); - - const [apiKeys, total] = await Promise.all([ - this.prisma.executeWithTimeout( - this.prisma.apiKey.findMany({ - skip, - take, - orderBy, - }), - 8000 // 8 second timeout for paginated query - ), - this.prisma.executeWithTimeout( - this.prisma.apiKey.count(), - 3000 // 3 second timeout for count query - ), - ]); - - const data = apiKeys.map(apiKey => this.mapToResponseDto(apiKey)); - return this.paginationService.formatResponse(data, total, normalizedQuery); - } - - async findOne(id: string): Promise { - const apiKey = await this.prisma.executeWithTimeout( - this.prisma.apiKey.findUnique({ - where: { id }, - }), - 3000 // 3 second timeout for find operation - ); - - if (!apiKey) { - throw new NotFoundException(`API key with ID ${id} not found`); - } - - return this.mapToResponseDto(apiKey); - } - - async update(id: string, updateApiKeyDto: UpdateApiKeyDto): Promise { - const input = await this.validateInput(UpdateApiKeyDto, updateApiKeyDto, 'update', { - skipMissingProperties: true, - }); - - if (input.scopes) { - this.validateScopes(input.scopes); - } - - const apiKey = await this.prisma.executeWithTimeout( - this.prisma.apiKey.findUnique({ - where: { id }, - }), - 3000 // 3 second timeout for find operation - ); - - if (!apiKey) { - throw new NotFoundException(`API key with ID ${id} not found`); - } - - const updatedApiKey = await this.prisma.executeWithTimeout( - this.prisma.apiKey.update({ - where: { id }, - data: input, - }), - 5000 // 5 second timeout for update operation - ); - - return this.mapToResponseDto(updatedApiKey); - } - - async revoke(id: string): Promise { - const apiKey = await this.prisma.executeWithTimeout( - this.prisma.apiKey.findUnique({ - where: { id }, - }), - 3000 // 3 second timeout for find operation - ); - - if (!apiKey) { - throw new NotFoundException(`API key with ID ${id} not found`); - } - - await this.prisma.executeWithTimeout( - this.prisma.apiKey.update({ - where: { id }, - data: { isActive: false, revokedAt: new Date() }, - }), - 5000 // 5 second timeout for revoke operation - ); - - await this.redis.del(`rate_limit:${apiKey.keyPrefix}`); - } - - async validateApiKey(plainKey: string): Promise { - if (!plainKey || !plainKey.startsWith('propchain_live_')) { - throw new UnauthorizedException('Invalid API key format'); - } - - const keyPrefix = this.extractKeyPrefix(plainKey); - - const apiKey = await this.prisma.apiKey.findFirst({ - where: { - keyPrefix, - isActive: true, - }, - }); - - if (!apiKey) { - throw new UnauthorizedException('Invalid or revoked API key'); - } - - const decryptedKey = this.decryptKey(apiKey.key); - - if (decryptedKey !== plainKey) { - throw new UnauthorizedException('Invalid API key'); - } - - await this.checkRateLimit(apiKey); - await this.trackUsage(apiKey.id, keyPrefix); - - return apiKey; // Return full API key object - } - - private async checkRateLimit(apiKey: any): Promise { - const limit = apiKey.rateLimit || this.globalRateLimit; - const redisKey = `rate_limit:${apiKey.keyPrefix}`; - - // Attempt to access the raw client property since getClient() doesn't exist - // Usually in these wrappers, it's called 'client' or 'redis' - const rawClient = (this.redis as any).client || (this.redis as any).redis; - - const currentCount = await this.redis.get(redisKey); - const count = currentCount ? parseInt(currentCount, 10) : 0; - - if (count >= limit) { - throw new UnauthorizedException('Rate limit exceeded'); - } - - if (rawClient) { - const ttl = await rawClient.ttl(redisKey); - if (ttl === -1 || ttl === -2) { - await this.redis.set(redisKey, '1'); - await rawClient.expire(redisKey, 60); - } else { - await rawClient.incr(redisKey); - } - } else { - // Fallback if rawClient access fails: - // Manual increment and reset logic (less accurate but doesn't crash) - const newCount = (count + 1).toString(); - await this.redis.set(redisKey, newCount); - } - } - - private async trackUsage(apiKeyId: string, keyPrefix: string): Promise { - await this.prisma.apiKey.update({ - where: { id: apiKeyId }, - data: { - requestCount: { increment: 1 }, - lastUsedAt: new Date(), - }, - }); - } - - private generateApiKey(): string { - const randomBytes = crypto.randomBytes(24); - const randomString = randomBytes - .toString('base64') - .replace(/\+/g, '') - .replace(/\//g, '') - .replace(/=/g, '') - .substring(0, 32); - - return `propchain_live_${randomString}`; - } - - private extractKeyPrefix(key: string): string { - return key.substring(0, 28); - } - - private encryptKey(plainKey: string): string { - return CryptoJS.AES.encrypt(plainKey, this.encryptionKey).toString(); - } - - private decryptKey(encryptedKey: string): string { - try { - const bytes = CryptoJS.AES.decrypt(encryptedKey, this.encryptionKey); - const decrypted = bytes.toString(CryptoJS.enc.Utf8); - if (!decrypted) { - throw new UnauthorizedException('Invalid API key format'); - } - return decrypted; - } catch (error) { - throw new UnauthorizedException('Invalid API key format'); - } - } - - private validateScopes(scopes: string[]): void { - const invalidScopes = scopes.filter(scope => !API_KEY_SCOPES.includes(scope as ApiKeyScope)); - - if (invalidScopes.length > 0) { - throw new BadRequestException( - `Invalid scopes: ${invalidScopes.join(', ')}. Valid scopes are: ${API_KEY_SCOPES.join(', ')}`, - ); - } - } - - private mapToResponseDto(apiKey: any): ApiKeyResponseDto { - return this.mapOutput(ApiKeyResponseDto, { - id: apiKey.id, - name: apiKey.name, - keyPrefix: apiKey.keyPrefix, - scopes: apiKey.scopes, - requestCount: apiKey.requestCount.toString(), - lastUsedAt: apiKey.lastUsedAt, - isActive: apiKey.isActive, - rateLimit: apiKey.rateLimit, - lastRotatedAt: apiKey.lastRotatedAt, - rotationDueAt: apiKey.rotationDueAt, - createdAt: apiKey.createdAt, - updatedAt: apiKey.updatedAt, - }); - } - - // ==================== KEY ROTATION METHODS ==================== - - /** - * Rotate an API key - generates a new key and deactivates the old one - */ - async rotateKey(id: string): Promise { - const apiKey = await this.prisma.apiKey.findUnique({ - where: { id }, - }); - - if (!apiKey) { - throw new NotFoundException(`API key with ID ${id} not found`); - } - - if (!apiKey.isActive) { - throw new BadRequestException('Cannot rotate a revoked API key'); - } - - // Generate new key - const newPlainKey = this.generateApiKey(); - const newKeyPrefix = this.extractKeyPrefix(newPlainKey); - const newEncryptedKey = this.encryptKey(newPlainKey); - - // Calculate new rotation due date - const newRotationDueAt = new Date(); - newRotationDueAt.setDate(newRotationDueAt.getDate() + this.rotationIntervalDays); - - // Update the API key with new values - const updatedKey = await this.prisma.apiKey.update({ - where: { id }, - data: { - key: newEncryptedKey, - keyPrefix: newKeyPrefix, - keyVersion: { increment: 1 }, - lastRotatedAt: new Date(), - rotationDueAt: newRotationDueAt, - }, - }); - - // Clear the old rate limit cache - await this.redis.del(`rate_limit:${apiKey.keyPrefix}`); - - this.logger.log(`Rotated API key ${id}: ${apiKey.keyPrefix} -> ${newKeyPrefix}`); - - return { - id: updatedKey.id, - name: updatedKey.name, - oldKeyPrefix: apiKey.keyPrefix, - newKeyPrefix, - key: newPlainKey, - rotatedAt: updatedKey.lastRotatedAt ?? new Date(), - }; - } - - /** - * Get rotation status for an API key - */ - async getRotationStatus(id: string): Promise { - const apiKey = await this.prisma.apiKey.findUnique({ - where: { id }, - }); - - if (!apiKey) { - throw new NotFoundException(`API key with ID ${id} not found`); - } - - const now = new Date(); - const rotationDueAt = apiKey.rotationDueAt; - const daysUntilRotation = rotationDueAt - ? Math.ceil((rotationDueAt.getTime() - now.getTime()) / (1000 * 60 * 60 * 24)) - : undefined; - - return { - id: apiKey.id, - name: apiKey.name, - keyPrefix: apiKey.keyPrefix, - lastRotatedAt: apiKey.lastRotatedAt || undefined, - rotationDueAt: rotationDueAt || undefined, - daysUntilRotation, - requiresRotation: daysUntilRotation !== undefined && daysUntilRotation <= 0, - }; - } - - /** - * Get all API keys that require rotation - */ - async getKeysRequiringRotation(): Promise { - const now = new Date(); - - const keys = await this.prisma.apiKey.findMany({ - where: { - isActive: true, - rotationDueAt: { lte: now }, - }, - }); - - return keys.map(apiKey => ({ - id: apiKey.id, - name: apiKey.name, - keyPrefix: apiKey.keyPrefix, - lastRotatedAt: apiKey.lastRotatedAt || undefined, - rotationDueAt: apiKey.rotationDueAt || undefined, - daysUntilRotation: 0, - requiresRotation: true, - })); - } - - /** - * Get API keys approaching rotation (within warning period) - */ - async getKeysApproachingRotation(): Promise { - const now = new Date(); - const warningDate = new Date(); - warningDate.setDate(warningDate.getDate() + this.rotationWarningDays); - - const keys = await this.prisma.apiKey.findMany({ - where: { - isActive: true, - rotationDueAt: { - gt: now, - lte: warningDate, - }, - }, - }); - - return keys.map(apiKey => { - const daysUntilRotation = apiKey.rotationDueAt - ? Math.ceil((apiKey.rotationDueAt.getTime() - now.getTime()) / (1000 * 60 * 60 * 24)) - : 0; - - return { - id: apiKey.id, - name: apiKey.name, - keyPrefix: apiKey.keyPrefix, - lastRotatedAt: apiKey.lastRotatedAt || undefined, - rotationDueAt: apiKey.rotationDueAt || undefined, - daysUntilRotation, - requiresRotation: false, - }; - }); - } - - /** - * Automatic rotation for all expired keys (called by scheduler) - */ - async autoRotateExpiredKeys(): Promise { - const expiredKeys = await this.getKeysRequiringRotation(); - const results: RotationResult[] = []; - - for (const key of expiredKeys) { - try { - const result = await this.rotateKey(key.id); - results.push(result); - this.logger.log(`Auto-rotated API key: ${key.name} (${key.id})`); - } catch (error) { - this.logger.error(`Failed to auto-rotate API key ${key.id}: ${error.message}`); - } - } - - return results; - } - - // ==================== USAGE ANALYTICS INTEGRATION ==================== - - /** - * Log detailed usage for analytics - */ - async logDetailedUsage( - apiKeyId: string, - endpoint: string, - method: string, - statusCode: number, - responseTime: number, - ipAddress?: string, - userAgent?: string, - ): Promise { - await this.analyticsService.logUsage({ - apiKeyId, - endpoint, - method, - statusCode, - responseTime, - ipAddress, - userAgent, - }); - } - - /** - * Get usage analytics for an API key - */ - async getUsageAnalytics(id: string, startDate: Date, endDate: Date) { - const apiKey = await this.prisma.apiKey.findUnique({ - where: { id }, - }); - - if (!apiKey) { - throw new NotFoundException(`API key with ID ${id} not found`); - } - - return this.analyticsService.getUsageReport(id, startDate, endDate); - } -} diff --git a/src/api-keys/api-key.types.ts b/src/api-keys/api-key.types.ts deleted file mode 100644 index 9e49cd25..00000000 --- a/src/api-keys/api-key.types.ts +++ /dev/null @@ -1,92 +0,0 @@ -// API Key type definitions - -export interface ApiKey { - id: string; - name: string; - key: string; - keyPrefix: string; - scopes: string[]; - requestCount: bigint; - lastUsedAt?: Date; - isActive: boolean; - rateLimit?: number; - createdAt: Date; - updatedAt: Date; -} - -export interface CreateApiKeyDto { - name: string; - scopes: string[]; - rateLimit?: number; -} - -export interface UpdateApiKeyDto { - name?: string; - scopes?: string[]; - rateLimit?: number; - isActive?: boolean; -} - -export interface ApiKeyQueryDto { - page?: number; - limit?: number; - isActive?: boolean; - search?: string; -} - -export interface ApiKeyResponseDto { - id: string; - name: string; - keyPrefix: string; - scopes: string[]; - requestCount: string; - lastUsedAt?: Date; - isActive: boolean; - rateLimit?: number; - createdAt: Date; - updatedAt: Date; -} - -export interface ApiKeyValidationResult { - isValid: boolean; - apiKey?: ApiKey; - error?: string; - remainingRequests?: number; - resetTime?: number; -} - -export interface ApiKeyRateLimitInfo { - limit: number; - remaining: number; - resetTime: number; - window: number; -} - -export interface ApiKeyUsageStats { - totalRequests: number; - requestsToday: number; - requestsThisMonth: number; - averageDailyRequests: number; - peakHour: number; - lastUsedAt?: Date; -} - -export interface ApiKeyScope { - resource: string; - action: string; - description: string; -} - -export interface ApiKeyWithUsage extends ApiKey { - usageStats: ApiKeyUsageStats; - rateLimitInfo: ApiKeyRateLimitInfo; -} - -export interface ApiKeyRequestContext { - apiKey?: ApiKey; - ipAddress: string; - userAgent: string; - timestamp: Date; - endpoint: string; - method: string; -} diff --git a/src/api-keys/api-keys.module.ts b/src/api-keys/api-keys.module.ts deleted file mode 100644 index 3fc54e04..00000000 --- a/src/api-keys/api-keys.module.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Module } from '@nestjs/common'; -import { ScheduleModule } from '@nestjs/schedule'; -import { ApiKeyService } from './api-key.service'; -import { ApiKeyController } from './api-key.controller'; -import { ApiKeyAnalyticsService } from './api-key-analytics.service'; -import { ApiKeyRotationScheduler } from './api-key-rotation.scheduler'; -import { PrismaModule } from '../database/prisma/prisma.module'; -import { PaginationService } from '../common/pagination'; -import { BoundaryValidationModule } from '../common/validation'; -import { CommunicationModule } from '../communication/communication.module'; - -@Module({ - imports: [PrismaModule, ScheduleModule.forRoot(), BoundaryValidationModule, CommunicationModule], - controllers: [ApiKeyController], - providers: [ApiKeyService, ApiKeyAnalyticsService, ApiKeyRotationScheduler, PaginationService], - exports: [ApiKeyService, ApiKeyAnalyticsService], -}) -export class ApiKeysModule {} diff --git a/src/api-keys/dto/api-key-query.dto.ts b/src/api-keys/dto/api-key-query.dto.ts deleted file mode 100644 index cc686599..00000000 --- a/src/api-keys/dto/api-key-query.dto.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { IsOptional, IsBoolean } from 'class-validator'; -import { ApiPropertyOptional } from '@nestjs/swagger'; -import { Transform } from 'class-transformer'; -import { IntersectionType } from '@nestjs/swagger'; -import { PaginationDto } from '../../common/dto'; - -export class ApiKeyFilterDto { - @ApiPropertyOptional({ - description: 'Filter by active status', - example: true, - }) - @IsOptional() - @Transform(({ value }) => value === 'true' || value === true) - @IsBoolean({ message: 'isActive must be a boolean' }) - isActive?: boolean; -} - -export class ApiKeyQueryDto extends IntersectionType(ApiKeyFilterDto, PaginationDto) {} diff --git a/src/api-keys/dto/api-key-response.dto.ts b/src/api-keys/dto/api-key-response.dto.ts deleted file mode 100644 index 485c1d3f..00000000 --- a/src/api-keys/dto/api-key-response.dto.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; - -export class ApiKeyResponseDto { - @ApiProperty({ example: 'cly1234567890abcdef' }) - id: string; - - @ApiProperty({ example: 'Production Integration Key' }) - name: string; - - @ApiProperty({ example: 'propchain_live_abc123...' }) - keyPrefix: string; - - @ApiProperty({ example: ['read:properties', 'write:properties'] }) - scopes: string[]; - - @ApiProperty({ example: 12345 }) - requestCount: string; - - @ApiProperty({ example: '2026-01-22T10:30:00.000Z', nullable: true }) - lastUsedAt: Date | null; - - @ApiProperty({ example: true }) - isActive: boolean; - - @ApiProperty({ example: 100, nullable: true }) - rateLimit: number | null; - - @ApiProperty({ example: '2026-01-15T08:00:00.000Z', nullable: true }) - lastRotatedAt?: Date; - - @ApiProperty({ example: '2026-04-15T08:00:00.000Z', nullable: true }) - rotationDueAt?: Date; - - @ApiProperty({ example: '2026-01-15T08:00:00.000Z' }) - createdAt: Date; - - @ApiProperty({ example: '2026-01-22T09:00:00.000Z' }) - updatedAt: Date; -} - -export class CreateApiKeyResponseDto extends ApiKeyResponseDto { - @ApiProperty({ - example: 'propchain_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6', - description: 'Full API key - shown only once at creation', - }) - key: string; -} diff --git a/src/api-keys/dto/create-api-key.dto.ts b/src/api-keys/dto/create-api-key.dto.ts deleted file mode 100644 index 6d06bb3c..00000000 --- a/src/api-keys/dto/create-api-key.dto.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { IsString, IsNotEmpty, IsArray, IsOptional, IsInt, Min, ArrayMinSize, MaxLength } from 'class-validator'; -import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; -import { ApiKeyScope } from '../enums/api-key-scope.enum'; - -export class CreateApiKeyDto { - @ApiProperty({ - description: 'Friendly name for the API key', - example: 'Production Integration Key', - maxLength: 100, - }) - @IsString({ message: 'Name must be a string' }) - @IsNotEmpty({ message: 'Name is required' }) - @MaxLength(100, { message: 'Name must not exceed 100 characters' }) - name!: string; - - @ApiProperty({ - description: 'Scopes/permissions for the API key', - example: ['read:properties', 'write:properties'], - enum: ApiKeyScope, - isArray: true, - }) - @IsArray({ message: 'Scopes must be an array' }) - @ArrayMinSize(1, { message: 'At least one scope is required' }) - @IsString({ each: true, message: 'Each scope must be a string' }) - scopes!: string[]; - - @ApiPropertyOptional({ - description: 'Rate limit (requests per minute) for this key. If not provided, uses global default.', - example: 100, - minimum: 1, - }) - @IsOptional() - @IsInt({ message: 'Rate limit must be an integer' }) - @Min(1, { message: 'Rate limit must be at least 1' }) - rateLimit?: number; -} diff --git a/src/api-keys/dto/index.ts b/src/api-keys/dto/index.ts deleted file mode 100644 index bd3086f6..00000000 --- a/src/api-keys/dto/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './create-api-key.dto'; -export * from './update-api-key.dto'; -export * from './api-key-response.dto'; -export * from './api-key-query.dto'; diff --git a/src/api-keys/dto/update-api-key.dto.ts b/src/api-keys/dto/update-api-key.dto.ts deleted file mode 100644 index 888f89e8..00000000 --- a/src/api-keys/dto/update-api-key.dto.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { IsString, IsOptional, IsArray, IsInt, Min, ArrayMinSize } from 'class-validator'; -import { ApiProperty } from '@nestjs/swagger'; -import { ApiKeyScope } from '../enums/api-key-scope.enum'; - -export class UpdateApiKeyDto { - @ApiProperty({ - description: 'Friendly name for the API key', - example: 'Updated Integration Key', - required: false, - }) - @IsOptional() - @IsString() - name?: string; - - @ApiProperty({ - description: 'Scopes/permissions for the API key', - example: ['read:properties'], - enum: ApiKeyScope, - isArray: true, - required: false, - }) - @IsOptional() - @IsArray() - @ArrayMinSize(1) - @IsString({ each: true }) - scopes?: string[]; - - @ApiProperty({ - description: 'Rate limit (requests per minute) for this key', - example: 200, - required: false, - }) - @IsOptional() - @IsInt() - @Min(1) - rateLimit?: number; -} diff --git a/src/api-keys/enums/api-key-scope.enum.ts b/src/api-keys/enums/api-key-scope.enum.ts deleted file mode 100644 index b051b310..00000000 --- a/src/api-keys/enums/api-key-scope.enum.ts +++ /dev/null @@ -1,7 +0,0 @@ -export enum ApiKeyScope { - READ_PROPERTIES = 'read:properties', - WRITE_PROPERTIES = 'write:properties', - READ_TRANSACTIONS = 'read:transactions', -} - -export const API_KEY_SCOPES = Object.values(ApiKeyScope); diff --git a/src/api-keys/examples/properties-with-api-keys.example.ts b/src/api-keys/examples/properties-with-api-keys.example.ts deleted file mode 100644 index 9eb5a55c..00000000 --- a/src/api-keys/examples/properties-with-api-keys.example.ts +++ /dev/null @@ -1,138 +0,0 @@ -/** - * EXAMPLE: How to protect routes with API Key authentication - * - * This is a sample implementation showing how to use the API key - * authentication system in your controllers. - */ - -import { Controller, Get, Post, Body, UseGuards, Req } from '@nestjs/common'; -import { ApiTags, ApiOperation, ApiSecurity } from '@nestjs/swagger'; -import { ApiKeyGuard } from '../../common/guards/api-key.guard'; -import { ApiKeyScopes } from '../../common/decorators/api-key-scopes.decorator'; - -@ApiTags('Properties') -@Controller('properties') -export class PropertiesExampleController { - /** - * EXAMPLE 1: Public endpoint (no authentication required) - */ - @Get('public') - @ApiOperation({ summary: 'Get public properties - no auth required' }) - getPublicProperties() { - return { - properties: [ - { id: '1', title: 'Public Property 1', price: 100000 }, - { id: '2', title: 'Public Property 2', price: 200000 }, - ], - }; - } - - /** - * EXAMPLE 2: Protected with API key - any valid key works - */ - @Get() - @UseGuards(ApiKeyGuard) - @ApiOperation({ summary: 'Get all properties - API key required' }) - @ApiSecurity('X-API-Key') - getAllProperties(@Req() req) { - return { - message: 'Authenticated with API key', - apiKeyId: req.apiKey?.id, - properties: [], - }; - } - - /** - * EXAMPLE 3: Protected with API key + read scope - */ - @Get('detailed') - @UseGuards(ApiKeyGuard) - @ApiKeyScopes('read:properties') - @ApiOperation({ summary: 'Get detailed properties - requires read:properties scope' }) - @ApiSecurity('X-API-Key') - getDetailedProperties(@Req() req) { - return { - message: 'Authenticated with read:properties scope', - apiKeyId: req.apiKey?.id, - properties: [], - }; - } - - /** - * EXAMPLE 4: Protected with API key + write scope - */ - @Post() - @UseGuards(ApiKeyGuard) - @ApiKeyScopes('write:properties') - @ApiOperation({ summary: 'Create property - requires write:properties scope' }) - @ApiSecurity('X-API-Key') - createProperty(@Body() data: any, @Req() req) { - return { - message: 'Property created with write:properties scope', - apiKeyId: req.apiKey?.id, - apiKeyName: req.apiKey?.name, - property: data, - }; - } - - /** - * EXAMPLE 5: Protected with API key + multiple scopes - */ - @Post('transfer') - @UseGuards(ApiKeyGuard) - @ApiKeyScopes('write:properties', 'read:transactions') - @ApiOperation({ summary: 'Transfer property - requires multiple scopes' }) - @ApiSecurity('X-API-Key') - transferProperty(@Body() data: any, @Req() req) { - return { - message: 'Property transfer initiated', - apiKeyId: req.apiKey?.id, - requiredScopes: ['write:properties', 'read:transactions'], - transfer: data, - }; - } -} - -/** - * USAGE EXAMPLES: - * - * 1. Create an API key via the management endpoint: - * - * POST /api-keys - * Authorization: Bearer - * { - * "name": "Mobile App", - * "scopes": ["read:properties", "write:properties"], - * "rateLimit": 100 - * } - * - * 2. Use the API key to access protected endpoints: - * - * GET /properties - * X-API-Key: propchain_live_abc123def456... - * - * or - * - * GET /properties - * Authorization: Bearer propchain_live_abc123def456... - * - * 3. The API key is validated automatically: - * - Format check (must start with 'propchain_') - * - Active status (not revoked) - * - Rate limit check - * - Scope verification (if @ApiKeyScopes decorator is used) - * - Usage tracking (increments requestCount, updates lastUsedAt) - * - * 4. Access the API key data in your handler: - * - * @Get() - * @UseGuards(ApiKeyGuard) - * myHandler(@Req() req) { - * const apiKey = req.apiKey; - * console.log('Key ID:', apiKey.id); - * console.log('Key Name:', apiKey.name); - * console.log('Scopes:', apiKey.scopes); - * console.log('Rate Limit:', apiKey.rateLimit); - * console.log('Request Count:', apiKey.requestCount); - * } - */ diff --git a/src/app.ci.module.ts b/src/app.ci.module.ts deleted file mode 100644 index 79f883ba..00000000 --- a/src/app.ci.module.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Module } from '@nestjs/common'; -import { ConfigModule } from '@nestjs/config'; -import { PrismaModule } from './database/prisma/prisma.module'; -import { HealthModule } from './health/health.module'; -import { SearchModule } from './search/search.module'; -import { AuditController } from './audit/audit.controller'; -import { AuditModule } from './audit/audit.module'; - -@Module({ - imports: [ - ConfigModule.forRoot({ - isGlobal: true, - envFilePath: ['.env.local', '.env.development', '.env'], - cache: true, - expandVariables: true, - }), - PrismaModule, - HealthModule, - SearchModule, - AuditModule, - ], - controllers: [AuditController], -}) -export class AppCiModule {} diff --git a/src/app.controller.ts b/src/app.controller.ts new file mode 100644 index 00000000..ad095825 --- /dev/null +++ b/src/app.controller.ts @@ -0,0 +1,17 @@ +import { Controller, Get } from '@nestjs/common'; + +@Controller() +export class AppController { + @Get() + getHello(): string { + return 'Welcome to PropChain API'; + } + + @Get('health') + health(): { status: string; timestamp: string } { + return { + status: 'OK', + timestamp: new Date().toISOString(), + }; + } +} diff --git a/src/app.module.ts b/src/app.module.ts index cab5fd0c..d4ff518e 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,225 +1,20 @@ -import { Module, NestModule, MiddlewareConsumer, ClassSerializerInterceptor } from '@nestjs/common'; -import { ConfigModule, ConfigService } from '@nestjs/config'; -import { ThrottlerModule } from '@nestjs/throttler'; -import { ScheduleModule } from '@nestjs/schedule'; -import { TerminusModule } from '@nestjs/terminus'; -import { BullModule } from '@nestjs/bull'; -import { APP_INTERCEPTOR, APP_FILTER } from '@nestjs/core'; - -// Core & Database -import { PrismaModule } from './database/prisma/prisma.module'; -import { HealthModule } from './health/health.module'; -import { ConfigurationModule } from './config/configuration.module'; -import configuration from './config/configuration'; -import valuationConfig from './config/valuation.config'; -import observabilityConfig from './config/observability.config'; - -// Caching -import { CacheModule } from './common/cache/cache.module'; - -// Logging -import { LoggingModule } from './common/logging/logging.module'; -import { LoggingInterceptor } from './common/logging/logging.interceptor'; -import { ResponseInterceptor } from './common/interceptors/response.interceptor'; -import { AllExceptionsFilter } from './common/errors/error.filter'; - -// I18n -import { I18nModule, AcceptLanguageResolver, QueryResolver, HeaderResolver } from 'nestjs-i18n'; -import * as path from 'path'; - -// Redis -import { RedisModule } from './common/services/redis.module'; -import { createRedisConfig } from './common/services/redis.config'; - -// Business Modules -import { PropertiesModule } from './properties/properties.module'; +import { Module } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; import { UsersModule } from './users/users.module'; -import { TransactionsModule } from './transactions/transactions.module'; -import { DonationsModule } from './donations/donations.module'; -import { WithdrawalsModule } from './withdrawals/withdrawals.module'; -import { BlockchainModule } from './blockchain/blockchain.module'; -import { AuthModule } from './auth/auth.module'; -import { FilesModule } from './files/files.module'; -import { ValuationModule } from './valuation/valuation.module'; -import { ApiKeysModule } from './api-keys/api-keys.module'; -import { DocumentsModule } from './documents/documents.module'; -import { SecurityModule } from './security/security.module'; -import { BackupRecoveryModule } from './backup-recovery/backup-recovery.module'; -import { GatewayModule } from './gateway/gateway.module'; -import { ErrorsModule } from './errors/errors.module'; - -// Compliance & Security Modules -import { AuditModule } from './common/audit/audit.module'; -import { RbacModule } from './rbac/rbac.module'; -import { AuditController } from './common/controllers/audit.controller'; -import { ComplianceModule } from './common/compliance/compliance.module'; - -// API Versioning -import { ApiVersionModule } from './common/api-version'; - -// Feature Flags -import { FeatureFlagModule } from './feature-flags/feature-flag.module'; -import { AnalyticsModule } from './analytics/analytics.module'; - -// Static Cache -import { StaticCacheModule } from './static-cache/static-cache.module'; - -// Data Export -import { ExportModule } from './export/export.module'; - -// Compression -import { CompressionModule } from './common/modules/compression.module'; -import { CompressionController } from './common/controllers/compression.controller'; - -// Middleware -import { HeaderValidationMiddleware } from './security/middleware/header-validation.middleware'; -import { RateLimitMiddleware } from './security/middleware/rate-limit.middleware'; -import { RequestValidationInterceptor } from './security/api/request.validation'; -import { StaticCacheMiddleware } from './static-cache/middleware/static-cache.middleware'; -import { ObservabilityModule } from './observability/observability.module'; -import { BoundaryValidationModule } from './common/validation'; +import { PropertiesModule } from './properties/properties.module'; +import { PrismaModule } from './database/prisma.module'; +import { AppController } from './app.controller'; @Module({ imports: [ - // Configuration ConfigModule.forRoot({ isGlobal: true, - load: [configuration, valuationConfig, observabilityConfig], - envFilePath: [ - `.env.${process.env.NODE_ENV || 'development'}.local`, - `.env.${process.env.NODE_ENV || 'development'}`, - '.env.local', - '.env', - ], - cache: true, - expandVariables: true, - }), - - ConfigurationModule, - BoundaryValidationModule, - - // I18n - I18nModule.forRootAsync({ - useFactory: (configService: ConfigService) => ({ - fallbackLanguage: configService.getOrThrow('FALLBACK_LANGUAGE', 'en'), - loaderOptions: { - path: path.join(__dirname, '/i18n/'), - watch: true, - }, - }), - resolvers: [{ use: QueryResolver, options: ['lang'] }, AcceptLanguageResolver, new HeaderResolver(['x-lang'])], - inject: [ConfigService], + envFilePath: ['.env.local', '.env'], }), - - // Caching - CacheModule, - - // Core - LoggingModule, PrismaModule, - HealthModule, - RedisModule, - - // Observability - ObservabilityModule, - - // Security & rate limiting - ThrottlerModule.forRootAsync({ - imports: [ConfigModule], - inject: [ConfigService], - useFactory: (configService: ConfigService) => [ - { - ttl: configService.get('THROTTLE_TTL', 60), - limit: configService.get('THROTTLE_LIMIT', 10), - }, - ], - }), - - // Background jobs - BullModule.forRootAsync({ - imports: [ConfigModule], - inject: [ConfigService], - useFactory: createRedisConfig, - }), - - // Scheduling & health - ScheduleModule.forRoot(), - TerminusModule, - - // Business - AuthModule, - ApiKeysModule, UsersModule, PropertiesModule, - TransactionsModule, - BlockchainModule, - FilesModule, - ValuationModule, - DocumentsModule, - SecurityModule, - ErrorsModule, - - // Compliance & Security - AuditModule, - RbacModule, - ComplianceModule, - - // API Versioning - ApiVersionModule, - BackupRecoveryModule, - - // Feature Flags - FeatureFlagModule, - AnalyticsModule, - - // Static Cache - StaticCacheModule, - - // Data Export - ExportModule, - - // Gateway - GatewayModule, - - // Donations - DonationsModule, - WithdrawalsModule, - - // Compression - CompressionModule, - ], - controllers: [AuditController, CompressionController], - providers: [ - { - provide: APP_INTERCEPTOR, - useClass: ClassSerializerInterceptor, - }, - { - provide: APP_INTERCEPTOR, - useClass: RequestValidationInterceptor, - }, - { - provide: APP_INTERCEPTOR, - useClass: ResponseInterceptor, - }, - { - provide: APP_INTERCEPTOR, - useClass: LoggingInterceptor, - }, - { - provide: APP_FILTER, - useClass: AllExceptionsFilter, - }, ], + controllers: [AppController], }) -export class AppModule implements NestModule { - configure(consumer: MiddlewareConsumer) { - consumer - .apply(StaticCacheMiddleware) - .forRoutes('*') - .apply(HeaderValidationMiddleware) - .forRoutes('*') - .apply(RateLimitMiddleware) - .forRoutes('*'); - } -} +export class AppModule {} diff --git a/src/audit/AuditLogger.ts b/src/audit/AuditLogger.ts deleted file mode 100644 index f841276b..00000000 --- a/src/audit/AuditLogger.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { PrismaService } from '../database/prisma/prisma.service'; -import { AuditLogAction, AuditLogSource, CreateAuditLogInput } from '../models/AuditLog'; -import { createHash } from 'crypto'; - -@Injectable() -export class AuditLogger { - private readonly logger = new Logger(AuditLogger.name); - - constructor(private readonly prisma: PrismaService) {} - - /** - * Log an action with GDPR compliance and data retention logic - */ - async log(input: CreateAuditLogInput) { - const { userId, action, source, resourceType, resourceId, ipAddress, userAgent, metadata } = input; - - // Sanitize metadata for GDPR (hash sensitive PII) - const sanitizedMetadata = this.sanitizeMetadata(metadata || {}); - const retentionDays = this.getRetentionDaysForAction(action); - const retentionUntil = new Date(); - retentionUntil.setDate(retentionUntil.getDate() + retentionDays); - - try { - // Logic for adding audit log row to DB via Prisma - // Assuming audit log name in prisma is 'auditLog' - // @ts-ignore - const log = await this.prisma.auditLog.create({ - data: { - userId, - action, - source, - resourceType, - resourceId, - ipAddress, - userAgent, - metadata: sanitizedMetadata, - isImmutable: true, - retentionUntil, - timestamp: new Date(), - }, - }); - this.logger.debug(`Audit log created: ${log.id} - ${action} on ${resourceType}`); - return log; - } catch (error) { - this.logger.error('Failed to save audit log', error); - // In critical systems, failure to audit log should perhaps block the action or trigger an alert - } - } - - private sanitizeMetadata(metadata: Record) { - const sensitiveKeys = ['email', 'phone', 'ssn', 'taxId', 'address']; - const sanitized = { ...metadata }; - - for (const key of sensitiveKeys) { - if (sanitized[key]) { - sanitized[`hashed_${key}`] = createHash('sha256').update(String(sanitized[key])).digest('hex'); - delete sanitized[key]; - } - } - return sanitized; - } - - private getRetentionDaysForAction(action: AuditLogAction): number { - switch (action) { - case AuditLogAction.DELETE: - return 2250; // ~7 years for deletion audit - case AuditLogAction.SECURITY_VIOLATION: - return 3650; // 10 years for security incidents - default: - return 365; // 1 year by default - } - } -} diff --git a/src/audit/ComplianceManager.ts b/src/audit/ComplianceManager.ts deleted file mode 100644 index 4d8c997b..00000000 --- a/src/audit/ComplianceManager.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { PrismaService } from '../database/prisma/prisma.service'; -import { AuditLogger } from './AuditLogger'; -import { AuditLogAction, AuditLogSource } from '../models/AuditLog'; - -@Injectable() -export class ComplianceManager { - private readonly logger = new Logger(ComplianceManager.name); - - constructor( - private readonly prisma: PrismaService, - private readonly auditLogger: AuditLogger - ) {} - - /** - * Data Export (Right to Access - GDPR Art. 15) - */ - async generateDataExport(userId: string) { - this.logger.log(`Generating HIPAA/GDPR data export for user: ${userId}`); - - // Logic for gathering user data across related tables - // @ts-ignore - const userData = await this.prisma.user.findUnique({ - where: { id: userId }, - include: { - // transactions: true, - // properties: true, - // we'd include everything identifying - }, - }); - - await this.auditLogger.log({ - userId, - action: AuditLogAction.EXPORT, - source: AuditLogSource.SYSTEM, - resourceType: 'User', - resourceId: userId, - ipAddress: 'Internal System', - userAgent: 'ComplianceManager/1.0', - }); - - return userData; - } - - /** - * Data Deletion (Right to be Forgotten - GDPR Art. 17) - */ - async anonymizeUser(userId: string) { - this.logger.log(`Anonymizing user: ${userId} for deletion request`); - - // We shouldn't necessarily delete the record, but anonymize it to maintain referential integrity - // @ts-ignore - await this.prisma.user.update({ - where: { id: userId }, - data: { - email: `deleted-${userId}@example.com`, - bio: 'Deleted user', - isVerified: false, - // etc - }, - }); - - await this.auditLogger.log({ - userId, - action: AuditLogAction.DELETE, - source: AuditLogSource.SYSTEM, - resourceType: 'User', - resourceId: userId, - ipAddress: 'Internal System', - userAgent: 'ComplianceManager/1.0', - }); - } - - /** - * Manage user consent for various data processing activities - */ - async updateConsent(userId: string, purpose: string, isConsented: boolean) { - // Logic for updating user preferences / consent table - // ... - // then audit it - await this.auditLogger.log({ - userId, - action: AuditLogAction.CONSENT_CHANGE, - source: AuditLogSource.API, - resourceType: 'UserConsent', - resourceId: `${userId}:${purpose}`, - ipAddress: 'System-Update', - userAgent: 'Browser-Request', - metadata: { purpose, isConsented }, - }); - } -} diff --git a/src/audit/ForensicAnalyzer.ts b/src/audit/ForensicAnalyzer.ts deleted file mode 100644 index 99874425..00000000 --- a/src/audit/ForensicAnalyzer.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { PrismaService } from '../database/prisma/prisma.service'; -import { AuditLogAction, AuditLogSource } from '../models/AuditLog'; - -@Injectable() -export class ForensicAnalyzer { - private readonly logger = new Logger(ForensicAnalyzer.name); - - constructor(private readonly prisma: PrismaService) {} - - /** - * Run forensic analysis to detect security violations or suspicious actions - */ - async detectSuspiciousActivity(userId: string) { - // Get last login logs for the user - // @ts-ignore - const recentLoginFailures = await this.prisma.auditLog.findMany({ - where: { - userId, - action: AuditLogAction.SECURITY_VIOLATION, // Could also look for LOGIN and check metadata for failure - timestamp: { gte: new Date(Date.now() - 3600000) }, // Past hour - }, - orderBy: { timestamp: 'desc' }, - take: 10, - }); - - if (recentLoginFailures.length > 5) { - this.logger.warn(`Suspicious login activity detected for user: ${userId}`); - return { - level: 'high', - threat: 'Likely brute force / credential stuffing attack', - evidence: recentLoginFailures.length, - actionRecommended: 'Lock account temporary and alert the user', - }; - } - - return { level: 'low', threat: 'No immediate issues detected' }; - } - - /** - * Trace the lifecycle of a resource through audit logs (e.g. tracking a property's history) - */ - async traceResourceHistory(resourceType: string, resourceId: string) { - // @ts-ignore - const history = await this.prisma.auditLog.findMany({ - where: { resourceType, resourceId }, - orderBy: { timestamp: 'asc' }, - }); - - return history; - } - - /** - * Detect data anomalies or potential breaches (e.g. unusual data exports) - */ - async detectDataHeist(userId: string) { - // Check for multiple export requests in a short time - // @ts-ignore - const exports = await this.prisma.auditLog.findMany({ - where: { - userId, - action: AuditLogAction.EXPORT, - timestamp: { gte: new Date(Date.now() - 86400000) }, // Past 24 hours - }, - }); - - if (exports.length > 2) { - this.logger.error(`Possible data breach: ${exports.length} data exports by user: ${userId}`); - return true; - } - return false; - } -} diff --git a/src/audit/audit.controller.ts b/src/audit/audit.controller.ts deleted file mode 100644 index 49a78498..00000000 --- a/src/audit/audit.controller.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Controller, Get, Query } from '@nestjs/common'; -import { ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger'; -import { AuditService, AuditReportFilters } from './audit.service'; -import { AuditAction } from './entities/audit-log.entity'; - -@ApiTags('Audit') -@Controller('audit') -export class AuditController { - constructor(private readonly auditService: AuditService) {} - - @Get() - @ApiOperation({ summary: 'Paginated audit log' }) - @ApiQuery({ name: 'from', required: false, type: String }) - @ApiQuery({ name: 'to', required: false, type: String }) - @ApiQuery({ name: 'action', required: false, enum: AuditAction }) - @ApiQuery({ name: 'actor', required: false, type: String }) - @ApiQuery({ name: 'page', required: false, type: Number }) - @ApiQuery({ name: 'limit', required: false, type: Number }) - findAll( - @Query('from') from = new Date(Date.now() - 30 * 86_400_000).toISOString(), - @Query('to') to = new Date().toISOString(), - @Query('action') action?: AuditAction, - @Query('actor') actor?: string, - @Query('page') page = 1, - @Query('limit') limit = 50, - ) { - const filters: AuditReportFilters = { - from: new Date(from), - to: new Date(to), - action, - actorAddress: actor, - }; - return this.auditService.findAll(filters, Number(page), Number(limit)); - } - - @Get('report') - @ApiOperation({ summary: 'Aggregated audit report' }) - report( - @Query('from') from = new Date(Date.now() - 30 * 86_400_000).toISOString(), - @Query('to') to = new Date().toISOString(), - ) { - return this.auditService.generateReport({ - from: new Date(from), - to: new Date(to), - }); - } -} diff --git a/src/audit/audit.module.ts b/src/audit/audit.module.ts deleted file mode 100644 index eafb0c33..00000000 --- a/src/audit/audit.module.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Module } from '@nestjs/common'; -import { ScheduleModule } from '@nestjs/schedule'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { Injectable as Inj, Logger as Log } from '@nestjs/common'; -import { Cron, CronExpression } from '@nestjs/schedule'; -import { AuditService } from './audit.service'; -import { AuditController } from './audit.controller'; -import { AuditInterceptor } from './interceptors/audit.interceptor'; -import { AuditLog } from './entities/audit-log.entity'; - -@Inj() -class AuditRetentionTask { - private readonly logger = new Log(AuditRetentionTask.name); - constructor(private readonly auditService: AuditService) {} - - @Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT) - async run() { - this.logger.log('Running audit retention policy…'); - await this.auditService.applyRetentionPolicy(); - } -} - -@Module({ - imports: [ScheduleModule.forRoot(), TypeOrmModule.forFeature([AuditLog])], - controllers: [AuditController], - providers: [AuditService, AuditInterceptor, AuditRetentionTask], - exports: [AuditService, AuditInterceptor], -}) -export class AuditModule {} diff --git a/src/audit/audit.service.ts b/src/audit/audit.service.ts deleted file mode 100644 index dc087549..00000000 --- a/src/audit/audit.service.ts +++ /dev/null @@ -1,157 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Between, LessThan, Repository } from 'typeorm'; -import { AuditLog, AuditAction } from './entities/audit-log.entity'; - -export interface AuditEntry { - action: AuditAction; - actorAddress?: string; - targetId?: string; - targetType?: string; - diff?: Record; - requestMeta?: Record; -} - -export interface AuditReportFilters { - from: Date; - to: Date; - action?: AuditAction; - actorAddress?: string; - targetType?: string; -} - -export interface AuditReportRow { - action: string; - count: number; -} - -export interface AuditReport { - totalEvents: number; - byAction: AuditReportRow[]; - byActor: { actorAddress: string; count: number }[]; - retentionDays: number; -} - -/** How long audit rows are retained — configurable per environment */ -const RETENTION_DAYS = Number(process.env.AUDIT_RETENTION_DAYS ?? 365); - -@Injectable() -export class AuditService { - private readonly logger = new Logger(AuditService.name); - - constructor( - @InjectRepository(AuditLog) - private readonly auditRepo: Repository, - ) {} - - // ─── Write ───────────────────────────────────────────────────────────────── - - /** - * Record an audit event. Fire-and-forget safe — errors are logged but - * never bubble up to the caller so a logging failure never breaks a - * business operation. - */ - async log(entry: AuditEntry): Promise { - await this.auditRepo.save(entry).catch(err => this.logger.error('Failed to write audit log', err)); - } - - // ─── Query ───────────────────────────────────────────────────────────────── - - async findAll(filters: AuditReportFilters, page = 1, limit = 50): Promise<{ data: AuditLog[]; total: number }> { - const where: Record = { - createdAt: Between(filters.from, filters.to), - }; - if (filters.action) { - where['action'] = filters.action; - } - if (filters.actorAddress) { - where['actorAddress'] = filters.actorAddress; - } - if (filters.targetType) { - where['targetType'] = filters.targetType; - } - - const [data, total] = await this.auditRepo.findAndCount({ - where, - order: { createdAt: 'DESC' }, - skip: (page - 1) * limit, - take: limit, - }); - - return { data, total }; - } - - // ─── Reporting ────────────────────────────────────────────────────────────── - - async generateReport(filters: AuditReportFilters): Promise { - const base = this.auditRepo - .createQueryBuilder('a') - .where('a.createdAt BETWEEN :from AND :to', { from: filters.from, to: filters.to }); - - if (filters.action) { - base.andWhere('a.action = :action', { action: filters.action }); - } - if (filters.actorAddress) { - base.andWhere('a.actorAddress = :actorAddress', { actorAddress: filters.actorAddress }); - } - if (filters.targetType) { - base.andWhere('a.targetType = :targetType', { targetType: filters.targetType }); - } - - const [byAction, byActor, totalRaw] = await Promise.all([ - base - .clone() - .select('a.action', 'action') - .addSelect('COUNT(*)', 'count') - .groupBy('a.action') - .orderBy('count', 'DESC') - .getRawMany<{ action: string; count: string }>(), - - base - .clone() - .select('a.actorAddress', 'actorAddress') - .addSelect('COUNT(*)', 'count') - .where('a.actorAddress IS NOT NULL') - .andWhere('a.createdAt BETWEEN :from AND :to', { from: filters.from, to: filters.to }) - .groupBy('a.actorAddress') - .orderBy('count', 'DESC') - .limit(20) - .getRawMany<{ actorAddress: string; count: string }>(), - - base.clone().select('COUNT(*)', 'total').getRawOne<{ total: string }>(), - ]); - - return { - totalEvents: parseInt(totalRaw?.total ?? '0', 10), - byAction: byAction.map(r => ({ action: r.action, count: Number(r.count) })), - byActor: byActor.map(r => ({ actorAddress: r.actorAddress, count: Number(r.count) })), - retentionDays: RETENTION_DAYS, - }; - } - - // ─── Retention ────────────────────────────────────────────────────────────── - - /** - * Delete audit rows older than RETENTION_DAYS. - * Called by a @Cron job in the module — runs nightly. - */ - async applyRetentionPolicy(): Promise { - const cutoff = new Date(); - cutoff.setDate(cutoff.getDate() - RETENTION_DAYS); - - const result = await this.auditRepo.delete({ createdAt: LessThan(cutoff) }); - const deleted = result.affected ?? 0; - - if (deleted > 0) { - this.logger.log(`Audit retention: deleted ${deleted} records older than ${RETENTION_DAYS} days`); - // Record the purge itself so there's a meta-audit trail - await this.log({ - action: AuditAction.CALL_SETTLED, // re-use closest action or add AUDIT_PURGE to the enum - targetType: 'audit_log', - diff: { deletedCount: deleted, cutoffDate: cutoff.toISOString() }, - }); - } - - return deleted; - } -} diff --git a/src/audit/entities/audit-log.entity.ts b/src/audit/entities/audit-log.entity.ts deleted file mode 100644 index 20dabc42..00000000 --- a/src/audit/entities/audit-log.entity.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Column, CreateDateColumn, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'; - -export enum AuditAction { - // Auth - LOGIN = 'AUTH_LOGIN', - LOGOUT = 'AUTH_LOGOUT', - // Users - USER_UPDATED = 'USER_UPDATED', - USER_FOLLOWED = 'USER_FOLLOWED', - USER_UNFOLLOWED = 'USER_UNFOLLOWED', - // Calls - CALL_CREATED = 'CALL_CREATED', - CALL_RESOLVED = 'CALL_RESOLVED', - CALL_SETTLED = 'CALL_SETTLED', - // Stakes - STAKE_PLACED = 'STAKE_PLACED', - ESCROW_RELEASED = 'ESCROW_RELEASED', - // Admin - ADMIN_CHANGED = 'ADMIN_CHANGED', - FEE_CHANGED = 'FEE_CHANGED', - OUTCOME_MANAGER_CHANGED = 'OUTCOME_MANAGER_CHANGED', -} - -@Entity('audit_log') -export class AuditLog { - @PrimaryGeneratedColumn('uuid') - id: string; - - @Index() - @Column({ type: 'enum', enum: AuditAction }) - action: AuditAction; - - /** The wallet address or system identity performing the action */ - @Index() - @Column({ nullable: true }) - actorAddress?: string; - - /** The entity being acted upon (e.g. call ID, user address) */ - @Index() - @Column({ nullable: true }) - targetId?: string; - - /** Entity type: 'call' | 'user' | 'stake' | 'contract' */ - @Column({ nullable: true }) - targetType?: string; - - /** JSON snapshot of what changed — { before, after } */ - @Column({ type: 'jsonb', nullable: true }) - diff?: Record; - - /** HTTP request metadata — IP, user-agent, etc. */ - @Column({ type: 'jsonb', nullable: true }) - requestMeta?: Record; - - @Index() - @CreateDateColumn({ type: 'timestamptz' }) - createdAt: Date; -} diff --git a/src/audit/interceptors/audit.interceptor.ts b/src/audit/interceptors/audit.interceptor.ts deleted file mode 100644 index 1f6b42cc..00000000 --- a/src/audit/interceptors/audit.interceptor.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common'; -import { Request } from 'express'; -import { Observable, tap } from 'rxjs'; -import { AuditAction } from '../entities/audit-log.entity'; -import { AuditService } from '../audit.service'; - -/** Maps HTTP method + route pattern to an AuditAction */ -const ROUTE_ACTION_MAP: Record = { - 'POST /users/:address/follow': AuditAction.USER_FOLLOWED, - 'POST /users/:address/unfollow': AuditAction.USER_UNFOLLOWED, - 'POST /calls': AuditAction.CALL_CREATED, - 'POST /calls/:id/resolve': AuditAction.CALL_RESOLVED, - 'POST /calls/:id/settle': AuditAction.CALL_SETTLED, - 'POST /calls/:id/stake': AuditAction.STAKE_PLACED, -}; - -@Injectable() -export class AuditInterceptor implements NestInterceptor { - constructor(private readonly auditService: AuditService) {} - - intercept(context: ExecutionContext, next: CallHandler): Observable { - const req = context.switchToHttp().getRequest(); - - // Only audit mutating methods - if (!['POST', 'PUT', 'PATCH', 'DELETE'].includes(req.method)) { - return next.handle(); - } - - return next.handle().pipe( - tap(() => { - const routeKey = `${req.method} ${req.route?.path ?? req.path}`; - const action = ROUTE_ACTION_MAP[routeKey]; - - if (!action) { - return; - } - - this.auditService.log({ - action, - actorAddress: (req as any).user?.address, - targetId: req.params?.id ?? req.params?.address, - requestMeta: { - ip: req.ip, - userAgent: req.headers['user-agent'], - method: req.method, - path: req.path, - }, - }); - }), - ); - } -} diff --git a/src/auth/OAuth2Provider.ts b/src/auth/OAuth2Provider.ts deleted file mode 100644 index 5ec67e1a..00000000 --- a/src/auth/OAuth2Provider.ts +++ /dev/null @@ -1,424 +0,0 @@ -import { Injectable, BadRequestException, UnauthorizedException } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; -import { HttpService } from '@nestjs/axios'; -import { lastValueFrom } from 'rxjs'; -import { v4 as uuidv4 } from 'uuid'; -import { RedisService } from '../../common/services/redis.service'; -import { StructuredLoggerService } from '../../common/logging/logger.service'; -import { UserService } from '../../users/user.service'; -import { JwtService } from '@nestjs/jwt'; - -export interface OAuth2ProviderConfig { - clientId: string; - clientSecret: string; - redirectUri: string; - authorizationUrl: string; - tokenUrl: string; - userInfoUrl: string; - scopes: string[]; -} - -export interface OAuth2UserInfo { - id: string; - email: string; - name?: string; - firstName?: string; - lastName?: string; - avatar?: string; - provider: string; -} - -export interface OAuth2StateData { - state: string; - provider: string; - redirectUri?: string; - createdAt: number; -} - -@Injectable() -export class OAuth2Provider { - private readonly providers: Map = new Map(); - private readonly stateExpiry = 600; // 10 minutes - private readonly tokenExpiry = 3600; // 1 hour - - constructor( - private readonly configService: ConfigService, - private readonly httpService: HttpService, - private readonly redisService: RedisService, - private readonly logger: StructuredLoggerService, - private readonly userService: UserService, - private readonly jwtService: JwtService, - ) { - this.logger.setContext('OAuth2Provider'); - this.initializeProviders(); - } - - private initializeProviders(): void { - // Google OAuth2 - this.providers.set('google', { - clientId: this.configService.get('GOOGLE_CLIENT_ID')!, - clientSecret: this.configService.get('GOOGLE_CLIENT_SECRET')!, - redirectUri: this.configService.get('GOOGLE_REDIRECT_URI')!, - authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth', - tokenUrl: 'https://oauth2.googleapis.com/token', - userInfoUrl: 'https://www.googleapis.com/oauth2/v2/userinfo', - scopes: ['openid', 'email', 'profile'], - }); - - // GitHub OAuth2 - this.providers.set('github', { - clientId: this.configService.get('GITHUB_CLIENT_ID')!, - clientSecret: this.configService.get('GITHUB_CLIENT_SECRET')!, - redirectUri: this.configService.get('GITHUB_REDIRECT_URI')!, - authorizationUrl: 'https://github.com/login/oauth/authorize', - tokenUrl: 'https://github.com/login/oauth/access_token', - userInfoUrl: 'https://api.github.com/user', - scopes: ['user:email'], - }); - - // Microsoft OAuth2 - this.providers.set('microsoft', { - clientId: this.configService.get('MICROSOFT_CLIENT_ID')!, - clientSecret: this.configService.get('MICROSOFT_CLIENT_SECRET')!, - redirectUri: this.configService.get('MICROSOFT_REDIRECT_URI')!, - authorizationUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize', - tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token', - userInfoUrl: 'https://graph.microsoft.com/v1.0/me', - scopes: ['openid', 'email', 'profile'], - }); - - // LinkedIn OAuth2 - this.providers.set('linkedin', { - clientId: this.configService.get('LINKEDIN_CLIENT_ID')!, - clientSecret: this.configService.get('LINKEDIN_CLIENT_SECRET')!, - redirectUri: this.configService.get('LINKEDIN_REDIRECT_URI')!, - authorizationUrl: 'https://www.linkedin.com/oauth/v2/authorization', - tokenUrl: 'https://www.linkedin.com/oauth/v2/accessToken', - userInfoUrl: 'https://api.linkedin.com/v2/people/~:(id,firstName,lastName,emailAddress,profilePicture(displayImage~:playableStreams))', - scopes: ['r_liteprofile', 'r_emailaddress'], - }); - } - - /** - * Generate OAuth2 authorization URL - */ - async getAuthorizationUrl(provider: string, redirectUri?: string): Promise<{ url: string; state: string }> { - const providerConfig = this.providers.get(provider); - if (!providerConfig) { - throw new BadRequestException(`Unsupported OAuth2 provider: ${provider}`); - } - - const state = uuidv4(); - const stateData: OAuth2StateData = { - state, - provider, - redirectUri, - createdAt: Date.now(), - }; - - // Store state in Redis with expiry - await this.redisService.setex( - `oauth2_state:${state}`, - this.stateExpiry, - JSON.stringify(stateData) - ); - - const params = new URLSearchParams({ - client_id: providerConfig.clientId, - redirect_uri: providerConfig.redirectUri, - response_type: 'code', - scope: providerConfig.scopes.join(' '), - state, - }); - - const authorizationUrl = `${providerConfig.authorizationUrl}?${params.toString()}`; - - this.logger.info('OAuth2 authorization URL generated', { - provider, - state, - redirectUri: providerConfig.redirectUri, - }); - - return { url: authorizationUrl, state }; - } - - /** - * Exchange authorization code for access token and user info - */ - async exchangeCodeForTokens( - provider: string, - code: string, - state: string, - ): Promise<{ user: OAuth2UserInfo; tokens: any }> { - // Verify state - const stateData = await this.verifyState(state, provider); - - const providerConfig = this.providers.get(provider); - if (!providerConfig) { - throw new BadRequestException(`Unsupported OAuth2 provider: ${provider}`); - } - - try { - // Exchange code for access token - const tokenResponse = await this.exchangeCode(providerConfig, code); - - // Get user info - const userInfo = await this.getUserInfo(providerConfig, tokenResponse.access_token); - - // Store tokens in Redis - const tokenKey = `oauth2_tokens:${userInfo.id}:${provider}`; - await this.redisService.setex( - tokenKey, - this.tokenExpiry, - JSON.stringify(tokenResponse) - ); - - this.logger.info('OAuth2 token exchange successful', { - provider, - userId: userInfo.id, - email: userInfo.email, - }); - - return { - user: userInfo, - tokens: tokenResponse, - }; - } catch (error) { - this.logger.error('OAuth2 token exchange failed', { - provider, - error: error.message, - code, - state, - }); - throw new UnauthorizedException('Failed to exchange authorization code'); - } - } - - /** - * Authenticate or create user from OAuth2 provider - */ - async authenticateUser(userInfo: OAuth2UserInfo): Promise<{ user: any; jwtToken: string }> { - // Check if user exists with this OAuth2 provider - let user = await this.userService.findByOAuth2Provider(userInfo.provider, userInfo.id); - - if (!user) { - // Check if user exists with the same email - const existingUser = await this.userService.findByEmail(userInfo.email); - - if (existingUser) { - // Link OAuth2 account to existing user - user = await this.userService.linkOAuth2Account( - existingUser.id, - userInfo.provider, - userInfo.id, - userInfo - ); - } else { - // Create new user - user = await this.userService.createFromOAuth2(userInfo); - } - } else { - // Update user info - user = await this.userService.updateOAuth2UserInfo(user.id, userInfo); - } - - // Generate JWT token - const payload = { - sub: user.id, - email: user.email, - authMethod: 'oauth2', - provider: userInfo.provider, - }; - - const jwtToken = this.jwtService.sign(payload); - - this.logger.info('OAuth2 user authentication successful', { - provider: userInfo.provider, - userId: user.id, - email: user.email, - }); - - return { user, jwtToken }; - } - - /** - * Refresh OAuth2 access token - */ - async refreshToken(provider: string, refreshToken: string): Promise { - const providerConfig = this.providers.get(provider); - if (!providerConfig) { - throw new BadRequestException(`Unsupported OAuth2 provider: ${provider}`); - } - - try { - const response = await lastValueFrom( - this.httpService.post( - providerConfig.tokenUrl, - { - client_id: providerConfig.clientId, - client_secret: providerConfig.clientSecret, - refresh_token: refreshToken, - grant_type: 'refresh_token', - }, - { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - } - ) - ); - - return response.data; - } catch (error) { - this.logger.error('OAuth2 token refresh failed', { - provider, - error: error.message, - }); - throw new UnauthorizedException('Failed to refresh access token'); - } - } - - /** - * Revoke OAuth2 access token - */ - async revokeToken(provider: string, accessToken: string): Promise { - const providerConfig = this.providers.get(provider); - if (!providerConfig) { - throw new BadRequestException(`Unsupported OAuth2 provider: ${provider}`); - } - - try { - // Note: Not all providers support token revocation - if (provider === 'google') { - await lastValueFrom( - this.httpService.post('https://oauth2.googleapis.com/revoke', { - token: accessToken, - }) - ); - } - - this.logger.info('OAuth2 token revoked', { provider }); - } catch (error) { - this.logger.error('OAuth2 token revocation failed', { - provider, - error: error.message, - }); - // Don't throw error as revocation is optional - } - } - - private async verifyState(state: string, provider: string): Promise { - const stateDataStr = await this.redisService.get(`oauth2_state:${state}`); - - if (!stateDataStr) { - throw new BadRequestException('Invalid or expired state'); - } - - const stateData: OAuth2StateData = JSON.parse(stateDataStr); - - if (stateData.provider !== provider) { - throw new BadRequestException('State provider mismatch'); - } - - if (Date.now() - stateData.createdAt > this.stateExpiry * 1000) { - throw new BadRequestException('State expired'); - } - - // Clean up state - await this.redisService.del(`oauth2_state:${state}`); - - return stateData; - } - - private async exchangeCode(providerConfig: OAuth2ProviderConfig, code: string): Promise { - const response = await lastValueFrom( - this.httpService.post( - providerConfig.tokenUrl, - { - client_id: providerConfig.clientId, - client_secret: providerConfig.clientSecret, - code, - grant_type: 'authorization_code', - redirect_uri: providerConfig.redirectUri, - }, - { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - } - ) - ); - - return response.data; - } - - private async getUserInfo(providerConfig: OAuth2ProviderConfig, accessToken: string): Promise { - const headers = { - Authorization: `Bearer ${accessToken}`, - }; - - const response = await lastValueFrom( - this.httpService.get(providerConfig.userInfoUrl, { headers }) - ); - - const data = response.data; - - // Transform response data based on provider - switch (providerConfig.authorizationUrl) { - case 'https://accounts.google.com/o/oauth2/v2/auth': - return { - id: data.id, - email: data.email, - name: data.name, - firstName: data.given_name, - lastName: data.family_name, - avatar: data.picture, - provider: 'google', - }; - - case 'https://github.com/login/oauth/authorize': - return { - id: data.id.toString(), - email: data.email, - name: data.name, - avatar: data.avatar_url, - provider: 'github', - }; - - case 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize': - return { - id: data.id, - email: data.mail || data.userPrincipalName, - name: data.displayName, - provider: 'microsoft', - }; - - case 'https://www.linkedin.com/oauth/v2/authorization': - return { - id: data.id, - email: data.emailAddress, - firstName: data.firstName.localized.en_US, - lastName: data.lastName.localized.en_US, - provider: 'linkedin', - }; - - default: - throw new BadRequestException('Unsupported OAuth2 provider for user info extraction'); - } - } - - /** - * Get list of supported OAuth2 providers - */ - getSupportedProviders(): string[] { - return Array.from(this.providers.keys()); - } - - /** - * Check if provider is configured - */ - isProviderConfigured(provider: string): boolean { - const config = this.providers.get(provider); - return !!(config?.clientId && config?.clientSecret); - } -} diff --git a/src/auth/SAMLProvider.ts b/src/auth/SAMLProvider.ts deleted file mode 100644 index 01684fbf..00000000 --- a/src/auth/SAMLProvider.ts +++ /dev/null @@ -1,513 +0,0 @@ -import { Injectable, BadRequestException, UnauthorizedException } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; -import { RedisService } from '../../common/services/redis.service'; -import { StructuredLoggerService } from '../../common/logging/logger.service'; -import { UserService } from '../../users/user.service'; -import { JwtService } from '@nestjs/jwt'; -import * as crypto from 'crypto'; -import * as xml2js from 'xml2js'; -import { v4 as uuidv4 } from 'uuid'; - -export interface SAMLEntityDescriptor { - entityID: string; - ssoURL: string; - sloURL?: string; - certificate: string; - nameIDFormat: string; -} - -export interface SAMLRequest { - id: string; - issuer: string; - assertionConsumerServiceURL: string; - destination: string; - timestamp: string; - relayState?: string; -} - -export interface SAMLResponse { - id: string; - issuer: string; - audience: string; - nameID: string; - nameIDFormat: string; - attributes: Record; - sessionIndex?: string; - notBefore: string; - notOnOrAfter: string; -} - -export interface SAMLUserInfo { - id: string; - email: string; - firstName?: string; - lastName?: string; - name?: string; - department?: string; - title?: string; - groups?: string[]; - provider: string; -} - -@Injectable() -export class SAMLProvider { - private readonly providers: Map = new Map(); - private readonly requestExpiry = 300; // 5 minutes - private readonly responseExpiry = 600; // 10 minutes - - constructor( - private readonly configService: ConfigService, - private readonly redisService: RedisService, - private readonly logger: StructuredLoggerService, - private readonly userService: UserService, - private readonly jwtService: JwtService, - ) { - this.logger.setContext('SAMLProvider'); - this.initializeProviders(); - } - - private initializeProviders(): void { - // Example SAML IdP configurations - // These should be configured based on your enterprise SSO setup - - // Azure AD SAML - this.providers.set('azure-ad', { - entityID: this.configService.get('AZURE_AD_ENTITY_ID')!, - ssoURL: this.configService.get('AZURE_AD_SSO_URL')!, - sloURL: this.configService.get('AZURE_AD_SLO_URL'), - certificate: this.configService.get('AZURE_AD_CERTIFICATE')!, - nameIDFormat: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', - }); - - // Okta SAML - this.providers.set('okta', { - entityID: this.configService.get('OKTA_ENTITY_ID')!, - ssoURL: this.configService.get('OKTA_SSO_URL')!, - sloURL: this.configService.get('OKTA_SLO_URL'), - certificate: this.configService.get('OKTA_CERTIFICATE')!, - nameIDFormat: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', - }); - - // ADFS SAML - this.providers.set('adfs', { - entityID: this.configService.get('ADFS_ENTITY_ID')!, - ssoURL: this.configService.get('ADFS_SSO_URL')!, - sloURL: this.configService.get('ADFS_SLO_URL'), - certificate: this.configService.get('ADFS_CERTIFICATE')!, - nameIDFormat: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', - }); - } - - /** - * Generate SAML authentication request - */ - async generateAuthRequest( - provider: string, - relayState?: string, - ): Promise<{ samlRequest: string; relayState: string; requestId: string }> { - const providerConfig = this.providers.get(provider); - if (!providerConfig) { - throw new BadRequestException(`Unsupported SAML provider: ${provider}`); - } - - const requestId = `_id_${uuidv4().replace(/-/g, '')}`; - const timestamp = new Date().toISOString(); - const assertionConsumerServiceURL = this.configService.get( - 'SAML_ASSERTION_CONSUMER_SERVICE_URL' - )!; - - const samlRequest: SAMLRequest = { - id: requestId, - issuer: this.configService.get('SAML_ENTITY_ID')!, - assertionConsumerServiceURL, - destination: providerConfig.ssoURL, - timestamp, - relayState, - }; - - // Store request in Redis - await this.redisService.setex( - `saml_request:${requestId}`, - this.requestExpiry, - JSON.stringify(samlRequest) - ); - - // Generate SAML AuthnRequest XML - const authnRequestXml = this.buildAuthnRequestXml(samlRequest, providerConfig); - - // Base64 encode the XML - const encodedRequest = Buffer.from(authnRequestXml).toString('base64'); - - // Generate relay state if not provided - const finalRelayState = relayState || uuidv4(); - - this.logger.info('SAML auth request generated', { - provider, - requestId, - relayState: finalRelayState, - }); - - return { - samlRequest: encodedRequest, - relayState: finalRelayState, - requestId, - }; - } - - /** - * Process SAML response - */ - async processResponse( - samlResponse: string, - relayState?: string, - ): Promise<{ user: SAMLUserInfo; jwtToken: string }> { - try { - // Decode SAML response - const decodedResponse = Buffer.from(samlResponse, 'base64').toString('utf-8'); - - // Parse and validate SAML response - const response = await this.parseAndValidateResponse(decodedResponse); - - // Extract user information - const userInfo = this.extractUserInfo(response); - - // Authenticate or create user - const { user, jwtToken } = await this.authenticateUser(userInfo); - - this.logger.info('SAML response processed successfully', { - provider: userInfo.provider, - userId: user.id, - email: user.email, - }); - - return { user: userInfo, jwtToken }; - } catch (error) { - this.logger.error('SAML response processing failed', { - error: error.message, - relayState, - }); - throw new UnauthorizedException('Invalid SAML response'); - } - } - - /** - * Generate SAML logout request - */ - async generateLogoutRequest( - provider: string, - nameID: string, - sessionIndex?: string, - ): Promise<{ samlRequest: string; relayState: string }> { - const providerConfig = this.providers.get(provider); - if (!providerConfig || !providerConfig.sloURL) { - throw new BadRequestException(`SLO not supported for provider: ${provider}`); - } - - const requestId = `_id_${uuidv4().replace(/-/g, '')}`; - const timestamp = new Date().toISOString(); - const relayState = uuidv4(); - - // Store logout request in Redis - await this.redisService.setex( - `saml_logout_request:${requestId}`, - this.requestExpiry, - JSON.stringify({ - requestId, - nameID, - sessionIndex, - timestamp, - provider, - }) - ); - - // Generate SAML LogoutRequest XML - const logoutRequestXml = this.buildLogoutRequestXml( - requestId, - nameID, - sessionIndex, - providerConfig - ); - - // Base64 encode the XML - const encodedRequest = Buffer.from(logoutRequestXml).toString('base64'); - - this.logger.info('SAML logout request generated', { - provider, - requestId, - nameID, - }); - - return { - samlRequest: encodedRequest, - relayState, - }; - } - - /** - * Process SAML logout response - */ - async processLogoutResponse(samlResponse: string): Promise { - try { - const decodedResponse = Buffer.from(samlResponse, 'base64').toString('utf-8'); - const parser = new xml2js.Parser(); - const result = await parser.parseStringPromise(decodedResponse); - - const response = result['samlp:LogoutResponse']; - if (!response) { - throw new Error('Invalid SAML logout response format'); - } - - const status = response['samlp:Status'][0]['samlp:StatusCode'][0].$.Value; - if (status !== 'urn:oasis:names:tc:SAML:2.0:status:Success') { - throw new Error('SAML logout failed'); - } - - this.logger.info('SAML logout response processed successfully'); - } catch (error) { - this.logger.error('SAML logout response processing failed', { - error: error.message, - }); - throw new UnauthorizedException('Invalid SAML logout response'); - } - } - - private buildAuthnRequestXml(request: SAMLRequest, provider: SAMLEntityDescriptor): string { - return ` - - ${request.issuer} - - - urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport - -`; - } - - private buildLogoutRequestXml( - requestId: string, - nameID: string, - sessionIndex: string | undefined, - provider: SAMLEntityDescriptor, - ): string { - return ` - - ${this.configService.get('SAML_ENTITY_ID')} - ${nameID} - ${sessionIndex ? `${sessionIndex}` : ''} -`; - } - - private async parseAndValidateResponse(xmlResponse: string): Promise { - const parser = new xml2js.Parser(); - const result = await parser.parseStringPromise(xmlResponse); - - const response = result['samlp:Response']; - if (!response) { - throw new Error('Invalid SAML response format'); - } - - const assertion = response['saml:Assertion']?.[0]; - if (!assertion) { - throw new Error('No SAML assertion found'); - } - - // Extract and validate response data - const responseId = response.$.ID; - const issuer = assertion['saml:Issuer'][0]; - const subject = assertion['saml:Subject'][0]; - const nameID = subject['saml:NameID'][0]; - const conditions = assertion['saml:Conditions'][0]; - const attributes = assertion['saml:AttributeStatement']?.[0]?.['saml:Attribute'] || []; - - // Validate timestamps - const notBefore = new Date(conditions.$.NotBefore); - const notOnOrAfter = new Date(conditions.$.NotOnOrAfter); - const now = new Date(); - - if (now < notBefore || now > notOnOrAfter) { - throw new Error('SAML response is not within valid time range'); - } - - // Extract attributes - const attributeMap: Record = {}; - attributes.forEach((attr: any) => { - const name = attr.$.Name; - const values = attr['saml:AttributeValue'].map((val: any) => val._ || val); - attributeMap[name] = values; - }); - - return { - id: responseId, - issuer, - audience: conditions['saml:AudienceRestriction'][0]['saml:Audience'][0], - nameID: nameID._ || nameID, - nameIDFormat: nameID.$.Format, - attributes: attributeMap, - sessionIndex: assertion['saml:AuthnStatement']?.[0]?.$.SessionIndex, - notBefore: conditions.$.NotBefore, - notOnOrAfter: conditions.$.NotOnOrAfter, - }; - } - - private extractUserInfo(response: SAMLResponse): SAMLUserInfo { - // Determine provider from issuer - let provider = 'unknown'; - for (const [key, config] of this.providers.entries()) { - if (response.issuer.includes(config.entityID)) { - provider = key; - break; - } - } - - // Extract user attributes (common SAML attribute names) - const email = response.attributes['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress']?.[0] || - response.attributes['email']?.[0] || - response.nameID; - - const firstName = response.attributes['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname']?.[0] || - response.attributes['firstName']?.[0]; - - const lastName = response.attributes['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname']?.[0] || - response.attributes['lastName']?.[0]; - - const name = response.attributes['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name']?.[0] || - response.attributes['name']?.[0]; - - const department = response.attributes['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/department']?.[0] || - response.attributes['department']?.[0]; - - const title = response.attributes['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/title']?.[0] || - response.attributes['title']?.[0]; - - const groups = response.attributes['http://schemas.microsoft.com/ws/2008/06/identity/claims/groups'] || - response.attributes['groups'] || - []; - - return { - id: response.nameID, - email: email || '', - firstName, - lastName, - name, - department, - title, - groups, - provider, - }; - } - - private async authenticateUser(userInfo: SAMLUserInfo): Promise<{ user: any; jwtToken: string }> { - // Check if user exists with this SAML provider - let user = await this.userService.findBySAMLProvider(userInfo.provider, userInfo.id); - - if (!user) { - // Check if user exists with the same email - const existingUser = await this.userService.findByEmail(userInfo.email); - - if (existingUser) { - // Link SAML account to existing user - user = await this.userService.linkSAMLAccount( - existingUser.id, - userInfo.provider, - userInfo.id, - userInfo - ); - } else { - // Create new user - user = await this.userService.createFromSAML(userInfo); - } - } else { - // Update user info - user = await this.userService.updateSAMLUserInfo(user.id, userInfo); - } - - // Generate JWT token - const payload = { - sub: user.id, - email: user.email, - authMethod: 'saml', - provider: userInfo.provider, - groups: userInfo.groups, - }; - - const jwtToken = this.jwtService.sign(payload); - - this.logger.info('SAML user authentication successful', { - provider: userInfo.provider, - userId: user.id, - email: user.email, - }); - - return { user, jwtToken }; - } - - /** - * Get list of supported SAML providers - */ - getSupportedProviders(): string[] { - return Array.from(this.providers.keys()); - } - - /** - * Check if provider is configured - */ - isProviderConfigured(provider: string): boolean { - const config = this.providers.get(provider); - return !!(config?.entityID && config?.ssoURL && config?.certificate); - } - - /** - * Get provider metadata - */ - getProviderMetadata(provider: string): string | null { - const config = this.providers.get(provider); - if (!config) { - return null; - } - - const entityID = this.configService.get('SAML_ENTITY_ID')!; - const assertionConsumerServiceURL = this.configService.get( - 'SAML_ASSERTION_CONSUMER_SERVICE_URL' - )!; - const sloURL = this.configService.get('SAML_SINGLE_LOGOUT_SERVICE_URL'); - - return ` - - - - - - ${this.configService.get('SAML_CERTIFICATE')} - - - - - ${sloURL ? ` - ` : ''} - -`; - } -} diff --git a/src/auth/SocialAuth.ts b/src/auth/SocialAuth.ts deleted file mode 100644 index 5dba4240..00000000 --- a/src/auth/SocialAuth.ts +++ /dev/null @@ -1,664 +0,0 @@ -import { Injectable, BadRequestException, UnauthorizedException } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; -import { HttpService } from '@nestjs/axios'; -import { lastValueFrom } from 'rxjs'; -import { RedisService } from '../../common/services/redis.service'; -import { StructuredLoggerService } from '../../common/logging/logger.service'; -import { UserService } from '../../users/user.service'; -import { JwtService } from '@nestjs/jwt'; -import { v4 as uuidv4 } from 'uuid'; - -export interface SocialProviderConfig { - clientId: string; - clientSecret: string; - redirectUri: string; - scopes: string[]; - apiBaseUrl: string; - tokenEndpoint: string; - userInfoEndpoint: string; -} - -export interface SocialUserInfo { - id: string; - email: string; - name?: string; - firstName?: string; - lastName?: string; - username?: string; - avatar?: string; - bio?: string; - location?: string; - website?: string; - followersCount?: number; - followingCount?: number; - verified?: boolean; - provider: string; - rawProfile?: any; -} - -export interface SocialAuthState { - state: string; - provider: string; - redirectUri?: string; - createdAt: number; -} - -@Injectable() -export class SocialAuth { - private readonly providers: Map = new Map(); - private readonly stateExpiry = 600; // 10 minutes - private readonly tokenExpiry = 3600; // 1 hour - - constructor( - private readonly configService: ConfigService, - private readonly httpService: HttpService, - private readonly redisService: RedisService, - private readonly logger: StructuredLoggerService, - private readonly userService: UserService, - private readonly jwtService: JwtService, - ) { - this.logger.setContext('SocialAuth'); - this.initializeProviders(); - } - - private initializeProviders(): void { - // Twitter/X OAuth2 - this.providers.set('twitter', { - clientId: this.configService.get('TWITTER_CLIENT_ID')!, - clientSecret: this.configService.get('TWITTER_CLIENT_SECRET')!, - redirectUri: this.configService.get('TWITTER_REDIRECT_URI')!, - scopes: ['tweet.read', 'users.read', 'offline.access'], - apiBaseUrl: 'https://api.twitter.com', - tokenEndpoint: 'https://api.twitter.com/2/oauth2/token', - userInfoEndpoint: 'https://api.twitter.com/2/users/me', - }); - - // Facebook Login - this.providers.set('facebook', { - clientId: this.configService.get('FACEBOOK_CLIENT_ID')!, - clientSecret: this.configService.get('FACEBOOK_CLIENT_SECRET')!, - redirectUri: this.configService.get('FACEBOOK_REDIRECT_URI')!, - scopes: ['email', 'public_profile'], - apiBaseUrl: 'https://graph.facebook.com', - tokenEndpoint: 'https://graph.facebook.com/v18.0/oauth/access_token', - userInfoEndpoint: 'https://graph.facebook.com/me', - }); - - // Instagram Basic Display - this.providers.set('instagram', { - clientId: this.configService.get('INSTAGRAM_CLIENT_ID')!, - clientSecret: this.configService.get('INSTAGRAM_CLIENT_SECRET')!, - redirectUri: this.configService.get('INSTAGRAM_REDIRECT_URI')!, - scopes: ['user_profile'], - apiBaseUrl: 'https://graph.instagram.com', - tokenEndpoint: 'https://api.instagram.com/oauth/access_token', - userInfoEndpoint: 'https://graph.instagram.com/me', - }); - - // Discord OAuth2 - this.providers.set('discord', { - clientId: this.configService.get('DISCORD_CLIENT_ID')!, - clientSecret: this.configService.get('DISCORD_CLIENT_SECRET')!, - redirectUri: this.configService.get('DISCORD_REDIRECT_URI')!, - scopes: ['identify', 'email'], - apiBaseUrl: 'https://discord.com/api', - tokenEndpoint: 'https://discord.com/api/oauth2/token', - userInfoEndpoint: 'https://discord.com/api/users/@me', - }); - - // Apple Sign In - this.providers.set('apple', { - clientId: this.configService.get('APPLE_CLIENT_ID')!, - clientSecret: this.configService.get('APPLE_CLIENT_SECRET')!, - redirectUri: this.configService.get('APPLE_REDIRECT_URI')!, - scopes: ['name', 'email'], - apiBaseUrl: 'https://appleid.apple.com', - tokenEndpoint: 'https://appleid.apple.com/auth/token', - userInfoEndpoint: '', // Apple provides user info in the initial auth response - }); - - // TikTok OAuth2 - this.providers.set('tiktok', { - clientId: this.configService.get('TIKTOK_CLIENT_ID')!, - clientSecret: this.configService.get('TIKTOK_CLIENT_SECRET')!, - redirectUri: this.configService.get('TIKTOK_REDIRECT_URI')!, - scopes: ['user.info.basic'], - apiBaseUrl: 'https://open.tiktokapis.com', - tokenEndpoint: 'https://open.tiktokapis.com/v2/oauth/token/', - userInfoEndpoint: 'https://open.tiktokapis.com/v2/user/info/', - }); - } - - /** - * Get social authentication URL - */ - async getAuthUrl(provider: string, redirectUri?: string): Promise<{ url: string; state: string }> { - const providerConfig = this.providers.get(provider); - if (!providerConfig) { - throw new BadRequestException(`Unsupported social provider: ${provider}`); - } - - const state = uuidv4(); - const stateData: SocialAuthState = { - state, - provider, - redirectUri, - createdAt: Date.now(), - }; - - // Store state in Redis with expiry - await this.redisService.setex( - `social_state:${state}`, - this.stateExpiry, - JSON.stringify(stateData) - ); - - let authUrl: string; - - switch (provider) { - case 'twitter': - authUrl = this.buildTwitterAuthUrl(providerConfig, state); - break; - case 'facebook': - authUrl = this.buildFacebookAuthUrl(providerConfig, state); - break; - case 'instagram': - authUrl = this.buildInstagramAuthUrl(providerConfig, state); - break; - case 'discord': - authUrl = this.buildDiscordAuthUrl(providerConfig, state); - break; - case 'apple': - authUrl = this.buildAppleAuthUrl(providerConfig, state); - break; - case 'tiktok': - authUrl = this.buildTikTokAuthUrl(providerConfig, state); - break; - default: - throw new BadRequestException(`Auth URL generation not implemented for: ${provider}`); - } - - this.logger.info('Social auth URL generated', { - provider, - state, - redirectUri: providerConfig.redirectUri, - }); - - return { url: authUrl, state }; - } - - /** - * Exchange authorization code for user information - */ - async exchangeCodeForUser( - provider: string, - code: string, - state: string, - additionalParams?: Record, - ): Promise<{ user: SocialUserInfo; tokens: any }> { - // Verify state - const stateData = await this.verifyState(state, provider); - - const providerConfig = this.providers.get(provider); - if (!providerConfig) { - throw new BadRequestException(`Unsupported social provider: ${provider}`); - } - - try { - // Exchange code for access token - const tokens = await this.exchangeCode(providerConfig, code); - - // Get user info - const userInfo = await this.getUserInfo(provider, tokens, additionalParams); - - // Store tokens in Redis - const tokenKey = `social_tokens:${userInfo.id}:${provider}`; - await this.redisService.setex( - tokenKey, - this.tokenExpiry, - JSON.stringify(tokens) - ); - - this.logger.info('Social auth code exchange successful', { - provider, - userId: userInfo.id, - email: userInfo.email, - }); - - return { user: userInfo, tokens }; - } catch (error) { - this.logger.error('Social auth code exchange failed', { - provider, - error: error.message, - code, - state, - }); - throw new UnauthorizedException('Failed to exchange authorization code'); - } - } - - /** - * Authenticate or create user from social provider - */ - async authenticateUser(userInfo: SocialUserInfo): Promise<{ user: any; jwtToken: string }> { - // Check if user exists with this social provider - let user = await this.userService.findBySocialProvider(userInfo.provider, userInfo.id); - - if (!user) { - // Check if user exists with the same email - const existingUser = await this.userService.findByEmail(userInfo.email); - - if (existingUser) { - // Link social account to existing user - user = await this.userService.linkSocialAccount( - existingUser.id, - userInfo.provider, - userInfo.id, - userInfo - ); - } else { - // Create new user - user = await this.userService.createFromSocial(userInfo); - } - } else { - // Update user info - user = await this.userService.updateSocialUserInfo(user.id, userInfo); - } - - // Generate JWT token - const payload = { - sub: user.id, - email: user.email, - authMethod: 'social', - provider: userInfo.provider, - verified: userInfo.verified, - }; - - const jwtToken = this.jwtService.sign(payload); - - this.logger.info('Social user authentication successful', { - provider: userInfo.provider, - userId: user.id, - email: user.email, - }); - - return { user, jwtToken }; - } - - /** - * Refresh social access token - */ - async refreshToken(provider: string, refreshToken: string): Promise { - const providerConfig = this.providers.get(provider); - if (!providerConfig) { - throw new BadRequestException(`Unsupported social provider: ${provider}`); - } - - try { - const response = await lastValueFrom( - this.httpService.post( - providerConfig.tokenEndpoint, - { - client_id: providerConfig.clientId, - client_secret: providerConfig.clientSecret, - refresh_token: refreshToken, - grant_type: 'refresh_token', - }, - { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - } - ) - ); - - return response.data; - } catch (error) { - this.logger.error('Social token refresh failed', { - provider, - error: error.message, - }); - throw new UnauthorizedException('Failed to refresh access token'); - } - } - - /** - * Revoke social access token - */ - async revokeToken(provider: string, accessToken: string): Promise { - try { - switch (provider) { - case 'facebook': - await lastValueFrom( - this.httpService.get( - `https://graph.facebook.com/me/permissions?access_token=${accessToken}` - ) - ); - break; - case 'discord': - await lastValueFrom( - this.httpService.post( - 'https://discord.com/api/oauth2/token/revoke', - `token=${accessToken}`, - { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - } - ) - ); - break; - // Note: Not all providers support token revocation - } - - this.logger.info('Social token revoked', { provider }); - } catch (error) { - this.logger.error('Social token revocation failed', { - provider, - error: error.message, - }); - // Don't throw error as revocation is optional - } - } - - private async verifyState(state: string, provider: string): Promise { - const stateDataStr = await this.redisService.get(`social_state:${state}`); - - if (!stateDataStr) { - throw new BadRequestException('Invalid or expired state'); - } - - const stateData: SocialAuthState = JSON.parse(stateDataStr); - - if (stateData.provider !== provider) { - throw new BadRequestException('State provider mismatch'); - } - - if (Date.now() - stateData.createdAt > this.stateExpiry * 1000) { - throw new BadRequestException('State expired'); - } - - // Clean up state - await this.redisService.del(`social_state:${state}`); - - return stateData; - } - - private async exchangeCode(providerConfig: SocialProviderConfig, code: string): Promise { - const response = await lastValueFrom( - this.httpService.post( - providerConfig.tokenEndpoint, - { - client_id: providerConfig.clientId, - client_secret: providerConfig.clientSecret, - code, - grant_type: 'authorization_code', - redirect_uri: providerConfig.redirectUri, - }, - { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - } - ) - ); - - return response.data; - } - - private async getUserInfo( - provider: string, - tokens: any, - additionalParams?: Record, - ): Promise { - const providerConfig = this.providers.get(provider); - if (!providerConfig) { - throw new BadRequestException(`Unsupported social provider: ${provider}`); - } - - const headers = { - Authorization: `Bearer ${tokens.access_token}`, - }; - - try { - let userInfo: SocialUserInfo; - - switch (provider) { - case 'twitter': - userInfo = await this.getTwitterUserInfo(headers, additionalParams); - break; - case 'facebook': - userInfo = await this.getFacebookUserInfo(headers); - break; - case 'instagram': - userInfo = await this.getInstagramUserInfo(headers); - break; - case 'discord': - userInfo = await this.getDiscordUserInfo(headers); - break; - case 'apple': - userInfo = await this.getAppleUserInfo(tokens, additionalParams); - break; - case 'tiktok': - userInfo = await this.getTikTokUserInfo(headers); - break; - default: - throw new BadRequestException(`User info extraction not implemented for: ${provider}`); - } - - userInfo.provider = provider; - return userInfo; - } catch (error) { - this.logger.error('Failed to get user info', { - provider, - error: error.message, - }); - throw error; - } - } - - private async getTwitterUserInfo(headers: any, additionalParams?: any): Promise { - const response = await lastValueFrom( - this.httpService.get('https://api.twitter.com/2/users/me', { - headers, - params: { - 'user.fields': 'created_at,description,location,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified', - }, - }) - ); - - const data = response.data.data; - return { - id: data.id, - username: data.username, - name: data.name, - bio: data.description, - location: data.location, - avatar: data.profile_image_url, - verified: data.verified, - followersCount: data.public_metrics?.followers_count, - followingCount: data.public_metrics?.following_count, - email: additionalParams?.email || '', // Email requires special scope - }; - } - - private async getFacebookUserInfo(headers: any): Promise { - const response = await lastValueFrom( - this.httpService.get('https://graph.facebook.com/me', { - headers, - params: { - fields: 'id,name,email,first_name,last_name,picture', - }, - }) - ); - - const data = response.data; - return { - id: data.id, - email: data.email, - name: data.name, - firstName: data.first_name, - lastName: data.last_name, - avatar: data.picture?.data?.url, - }; - } - - private async getInstagramUserInfo(headers: any): Promise { - const response = await lastValueFrom( - this.httpService.get('https://graph.instagram.com/me', { - headers, - params: { - fields: 'id,username,account_type,media_count', - }, - }) - ); - - const data = response.data; - return { - id: data.id, - username: data.username, - }; - } - - private async getDiscordUserInfo(headers: any): Promise { - const response = await lastValueFrom( - this.httpService.get('https://discord.com/api/users/@me', { headers }) - ); - - const data = response.data; - return { - id: data.id, - email: data.email, - username: data.username, - name: data.global_name || data.username, - avatar: data.avatar ? `https://cdn.discordapp.com/avatars/${data.id}/${data.avatar}.png` : undefined, - verified: data.verified, - }; - } - - private async getAppleUserInfo(tokens: any, additionalParams?: any): Promise { - // Apple provides user info in the initial auth response - const user = additionalParams?.user; - const email = additionalParams?.email || tokens.email; - - return { - id: tokens.sub, - email: email || '', - firstName: user?.name?.firstName, - lastName: user?.name?.lastName, - name: user ? `${user.name?.firstName || ''} ${user.name?.lastName || ''}`.trim() : undefined, - }; - } - - private async getTikTokUserInfo(headers: any): Promise { - const response = await lastValueFrom( - this.httpService.get('https://open.tiktokapis.com/v2/user/info/', { - headers, - }) - ); - - const data = response.data.data.user; - return { - id: data.open_id, - username: data.display_name, - avatar: data.avatar_url, - verified: data.is_verified, - }; - } - - private buildTwitterAuthUrl(config: SocialProviderConfig, state: string): string { - const params = new URLSearchParams({ - response_type: 'code', - client_id: config.clientId, - redirect_uri: config.redirectUri, - scope: config.scopes.join(' '), - state, - code_challenge: this.generateCodeChallenge(), - code_challenge_method: 'S256', - }); - - return `https://twitter.com/i/oauth2/authorize?${params.toString()}`; - } - - private buildFacebookAuthUrl(config: SocialProviderConfig, state: string): string { - const params = new URLSearchParams({ - client_id: config.clientId, - redirect_uri: config.redirectUri, - response_type: 'code', - scope: config.scopes.join(' '), - state, - }); - - return `https://www.facebook.com/v18.0/dialog/oauth?${params.toString()}`; - } - - private buildInstagramAuthUrl(config: SocialProviderConfig, state: string): string { - const params = new URLSearchParams({ - app_id: config.clientId, - redirect_uri: config.redirectUri, - response_type: 'code', - scope: config.scopes.join(' '), - state, - }); - - return `https://api.instagram.com/oauth/authorize?${params.toString()}`; - } - - private buildDiscordAuthUrl(config: SocialProviderConfig, state: string): string { - const params = new URLSearchParams({ - client_id: config.clientId, - redirect_uri: config.redirectUri, - response_type: 'code', - scope: config.scopes.join(' '), - state, - }); - - return `https://discord.com/api/oauth2/authorize?${params.toString()}`; - } - - private buildAppleAuthUrl(config: SocialProviderConfig, state: string): string { - const params = new URLSearchParams({ - client_id: config.clientId, - redirect_uri: config.redirectUri, - response_type: 'code', - scope: config.scopes.join(' '), - state, - response_mode: 'form_post', - }); - - return `https://appleid.apple.com/auth/authorize?${params.toString()}`; - } - - private buildTikTokAuthUrl(config: SocialProviderConfig, state: string): string { - const params = new URLSearchParams({ - client_key: config.clientId, - redirect_uri: config.redirectUri, - response_type: 'code', - scope: config.scopes.join(' '), - state, - }); - - return `https://www.tiktok.com/v2/auth/authorize?${params.toString()}`; - } - - private generateCodeChallenge(): string { - const verifier = uuidv4() + uuidv4(); - const hash = crypto.createHash('sha256').update(verifier).digest('base64url'); - return hash; - } - - /** - * Get list of supported social providers - */ - getSupportedProviders(): string[] { - return Array.from(this.providers.keys()); - } - - /** - * Check if provider is configured - */ - isProviderConfigured(provider: string): boolean { - const config = this.providers.get(provider); - return !!(config?.clientId && config?.clientSecret); - } -} diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts deleted file mode 100644 index 5f0bb63b..00000000 --- a/src/auth/auth.controller.ts +++ /dev/null @@ -1,456 +0,0 @@ -import { Controller, Post, Body, Req, Get, UseGuards, HttpCode, HttpStatus, Put, Param, Delete } from '@nestjs/common'; -import { AuthService } from './auth.service'; -import { JwtAuthGuard } from './guards/jwt-auth.guard'; -import { LoginAttemptsGuard } from './guards/login-attempts.guard'; -import { CreateUserDto } from '../users/dto/create-user.dto'; -import { - LoginDto, - LoginWeb3Dto, - RefreshTokenDto, - ForgotPasswordDto, - ResetPasswordDto, - VerifyEmailParamsDto, -} from './dto'; -import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth, ApiParam } from '@nestjs/swagger'; -import { Request } from 'express'; -import { ErrorResponseDto } from '../common/errors/error.dto'; -import { ApiStandardErrorResponse } from '../common/errors/api-standard-error-response.decorator'; -import { SensitiveEndpointRateLimitGuard } from '../security/guards/sensitive-endpoint-rate-limit.guard'; -import { SensitiveRateLimit } from '../security/decorators/sensitive-rate-limit.decorator'; - -/** - * AuthController - * - * Handles all authentication endpoints including user registration, login (traditional and Web3), - * token management, password reset, email verification, and session management. - * - * All endpoints that require authentication are protected with JwtAuthGuard. - * Login attempts are rate-limited to prevent brute-force attacks. - */ -@ApiTags('authentication') -@Controller('auth') -export class AuthController { - constructor(private authService: AuthService) {} - - /** - * Register a new user account - * - * Creates a new user with email and password credentials. Validates password strength - * and checks for duplicate email addresses. Sends verification email upon success. - * - * @param {CreateUserDto} createUserDto - User registration data - * @returns {Promise<{message: string}>} Success message with verification instructions - * - * @example - * ```json - * { - * "email": "user@example.com", - * "password": "SecurePass123!", - * "firstName": "John", - * "lastName": "Doe" - * } - * ``` - */ - @Post('register') - @ApiOperation({ - summary: 'Register a new user account', - description: - 'Creates a new user account with email/password. Sends verification email. Password must be at least 8 characters with uppercase, lowercase, number, and special character.', - }) - @ApiResponse({ - status: 201, - description: 'User registered successfully. Verification email sent.', - schema: { - properties: { - message: { type: 'string', example: 'User registered successfully. Please check your email for verification.' }, - }, - }, - }) - @ApiStandardErrorResponse([400, 409]) - async register(@Body() createUserDto: CreateUserDto) { - return this.authService.register(createUserDto); - } - - /** - * Authenticate user with email and password - * - * Traditional email/password authentication. Enforces rate limiting after failed attempts. - * Returns JWT access token (short-lived) and refresh token (long-lived). - * - * @param {LoginDto} loginDto - Email and password credentials - * @param {Request} req - Express request object - * @returns {Promise<{access_token: string, refresh_token: string, user: object}>} Auth tokens - */ - @Post('login') - @UseGuards(LoginAttemptsGuard) - @ApiOperation({ - summary: 'Login with email and password', - description: - 'Authenticates user with email and password. Returns access token (valid 15m) and refresh token (valid 7d). Rate limit: 5 attempts per 10 minutes.', - }) - @ApiResponse({ - status: 200, - description: 'Login successful.', - schema: { - properties: { - access_token: { type: 'string', description: 'JWT access token for API requests' }, - refresh_token: { type: 'string', description: 'JWT refresh token for obtaining new access tokens' }, - user: { type: 'object', description: 'User information' }, - }, - }, - }) - @ApiStandardErrorResponse([400, 401]) - @HttpCode(HttpStatus.OK) - async login(@Body() loginDto: LoginDto, @Req() req: Request) { - return this.authService.login( - { - email: loginDto.email, - password: loginDto.password, - }, - this.getRequestMeta(req), - ); - } - - /** - * Web3 wallet authentication - * - * Authenticates user via blockchain wallet address and signature. - * Automatically creates account for new wallet addresses (JIT provisioning). - * - * @param {LoginWeb3Dto} loginDto - Wallet address and signature - * @returns {Promise<{access_token: string, refresh_token: string, user: object}>} Auth tokens - */ - @Post('web3-login') - @ApiOperation({ - summary: 'Web3 wallet login', - description: - 'Authenticates user via blockchain wallet signature. Creates account automatically if wallet not registered. Supports Ethereum-based networks.', - }) - @ApiResponse({ - status: 200, - description: 'Web3 login successful.', - schema: { - properties: { - access_token: { type: 'string' }, - refresh_token: { type: 'string' }, - user: { type: 'object' }, - }, - }, - }) - @ApiStandardErrorResponse([401]) - @HttpCode(HttpStatus.OK) - async web3Login(@Body() loginDto: LoginWeb3Dto, @Req() req: Request) { - return this.authService.login( - { - walletAddress: loginDto.walletAddress, - signature: loginDto.signature, - }, - this.getRequestMeta(req), - ); - } - - /** - * Refresh access token - * - * Exchanges an expired or expiring access token for a new one using a refresh token. - * Implements token rotation for enhanced security. - * - * @param {RefreshTokenDto} refreshTokenDto - Refresh token - * @returns {Promise<{access_token: string, refresh_token: string}>} New token pair - */ - @Post('refresh-token') - @UseGuards(SensitiveEndpointRateLimitGuard) - @SensitiveRateLimit({ - windowMs: 60000, - maxRequests: 10, - keyPrefix: 'token_refresh', - enableProgressiveDelay: false, - blockOnExceed: false, - }) - @ApiOperation({ - summary: 'Refresh access token', - description: - 'Exchanges refresh token for new access token. Implements token rotation. Rate limit: 10 requests per minute.', - }) - @ApiResponse({ - status: 200, - description: 'Token refreshed successfully.', - schema: { - properties: { - access_token: { type: 'string' }, - refresh_token: { type: 'string' }, - user: { type: 'object' }, - }, - }, - }) - @ApiStandardErrorResponse([401]) - @HttpCode(HttpStatus.OK) - async refreshToken(@Body() refreshTokenDto: RefreshTokenDto, @Req() req: Request) { - return this.authService.refreshToken(refreshTokenDto.refreshToken, this.getRequestMeta(req)); - } - - /** - * Logout user - * - * Invalidates current session by blacklisting access token and revoking refresh token. - * Requires authentication with valid JWT token. - * - * @param {Request} req - Express request with user context - * @returns {Promise<{message: string}>} Logout confirmation - */ - @Post('logout') - @UseGuards(JwtAuthGuard) - @ApiBearerAuth() - @ApiOperation({ - summary: 'Logout current user', - description: 'Invalidates current session by blacklisting tokens. Requires valid access token.', - }) - @ApiResponse({ - status: 200, - description: 'Logged out successfully.', - schema: { - properties: { - message: { type: 'string', example: 'Logged out successfully' }, - }, - }, - }) - @ApiStandardErrorResponse([401]) - @HttpCode(HttpStatus.OK) - async logout(@Req() req: Request) { - const user = req['user'] as any; - const authHeader = req.headers['authorization']; - const accessToken = authHeader?.startsWith('Bearer ') ? authHeader.substring(7) : undefined; - return this.authService.logout(user.id, accessToken); - } - - /** - * Request password reset - * - * Initiates password reset flow by sending reset link to user email. - * Returns generic message regardless of email existence to prevent enumeration. - * - * @param {ForgotPasswordDto} forgotPasswordDto - User email address - * @returns {Promise<{message: string}>} Generic success message - */ - @Post('forgot-password') - @UseGuards(SensitiveEndpointRateLimitGuard) - @SensitiveRateLimit({ - windowMs: 900000, - maxRequests: 3, - keyPrefix: 'password_reset', - enableProgressiveDelay: true, - blockOnExceed: true, - blockDurationMs: 1800000, - }) - @ApiOperation({ - summary: 'Request password reset email', - description: - 'Sends password reset link to user email. Returns generic message for security. Rate limit: 3 requests per 15 minutes.', - }) - @ApiResponse({ - status: 200, - description: 'Password reset email sent (if email exists).', - schema: { - properties: { - message: { type: 'string', example: 'If email exists, a reset link has been sent' }, - }, - }, - }) - @HttpCode(HttpStatus.OK) - async forgotPassword(@Body() forgotPasswordDto: ForgotPasswordDto) { - return this.authService.forgotPassword(forgotPasswordDto.email); - } - - /** - * Reset password with token - * - * Completes password reset using token from email. Validates token hasn't expired. - * New password must meet strength requirements. - * - * @param {ResetPasswordDto} resetPasswordDto - Reset token and new password - * @returns {Promise<{message: string}>} Success message - */ - @Put('reset-password') - @UseGuards(SensitiveEndpointRateLimitGuard) - @SensitiveRateLimit({ - windowMs: 900000, - maxRequests: 5, - keyPrefix: 'password_reset_confirm', - enableProgressiveDelay: true, - blockOnExceed: true, - blockDurationMs: 3600000, - }) - @ApiOperation({ - summary: 'Reset password using reset token', - description: - 'Sets new password using token from password reset email. Token valid for 1 hour. Rate limit: 5 requests per 15 minutes.', - }) - @ApiResponse({ - status: 200, - description: 'Password reset successfully.', - schema: { - properties: { - message: { type: 'string', example: 'Password reset successfully' }, - }, - }, - }) - @ApiStandardErrorResponse([400]) - @HttpCode(HttpStatus.OK) - async resetPassword(@Body() resetPasswordDto: ResetPasswordDto) { - return this.authService.resetPassword(resetPasswordDto.token, resetPasswordDto.newPassword); - } - - /** - * Verify email address - * - * Marks user email as verified using token from verification email. - * Token expires after 1 hour. - * - * @param {VerifyEmailParamsDto} params - Email verification token - * @returns {Promise<{message: string}>} Verification success message - */ - @Get('verify-email/:token') - @ApiOperation({ - summary: 'Verify email address', - description: 'Confirms email ownership using token from verification email. Token valid for 1 hour.', - }) - @ApiResponse({ - status: 200, - description: 'Email verified successfully.', - schema: { - properties: { - message: { type: 'string', example: 'Email verified successfully' }, - }, - }, - }) - @ApiResponse({ - status: 400, - description: 'Invalid, expired, or already-used verification token.', - type: ErrorResponseDto, - }) - @ApiStandardErrorResponse([400]) - async verifyEmail(@Param() params: VerifyEmailParamsDto) { - return this.authService.verifyEmail(params.token); - } - - /** - * Get all active sessions - * - * Returns list of all active sessions for authenticated user. - * Requires valid JWT access token. - * - * @param {Request} req - Express request with user context - * @returns {Promise} List of active sessions with metadata - */ - @Get('sessions') - @UseGuards(JwtAuthGuard) - @ApiBearerAuth() - @ApiOperation({ - summary: 'Get all active sessions for current user', - description: 'Lists all active sessions with IP, user agent, and expiration time.', - }) - @ApiResponse({ - status: 200, - description: 'Sessions retrieved successfully.', - schema: { - type: 'array', - items: { - type: 'object', - properties: { - userId: { type: 'string' }, - createdAt: { type: 'string', format: 'date-time' }, - userAgent: { type: 'string' }, - ip: { type: 'string' }, - expiresIn: { type: 'number' }, - }, - }, - }, - }) - @ApiStandardErrorResponse([401]) - @HttpCode(HttpStatus.OK) - async getSessions(@Req() req: Request) { - const user = req['user'] as any; - return this.authService.getAllUserSessions(user.id); - } - - /** - * Invalidate specific session - * - * Logs out a specific session by session ID. Useful for remote logout - * of specific devices without affecting other sessions. - * - * @param {Request} req - Express request with user context - * @param {string} sessionId - ID of session to invalidate - * @returns {Promise<{message: string}>} Success confirmation - */ - @Delete('sessions/:sessionId') - @UseGuards(JwtAuthGuard) - @ApiBearerAuth() - @ApiOperation({ - summary: 'Invalidate a specific session', - description: 'Logs out a specific device/session without affecting other user sessions.', - }) - @ApiResponse({ - status: 200, - description: 'Session invalidated successfully.', - schema: { - properties: { - message: { type: 'string', example: 'Session invalidated successfully' }, - }, - }, - }) - @ApiStandardErrorResponse([401]) - @HttpCode(HttpStatus.OK) - async invalidateSession(@Req() req: Request, @Param('sessionId') sessionId: string) { - const user = req['user'] as any; - await this.authService.invalidateSession(user.id, sessionId); - return { message: 'Session invalidated successfully' }; - } - - /** - * Invalidate all sessions - * - * Logs out all sessions for the authenticated user. - * Useful for account security after password change or suspected breach. - * - * @param {Request} req - Express request with user context - * @returns {Promise<{message: string}>} Success confirmation - */ - @Delete('sessions') - @UseGuards(JwtAuthGuard) - @ApiBearerAuth() - @ApiOperation({ - summary: 'Invalidate all sessions for current user', - description: 'Logs out all devices/sessions. Useful after password change or security incident.', - }) - @ApiResponse({ - status: 200, - description: 'All sessions invalidated successfully.', - schema: { - properties: { - message: { type: 'string', example: 'All sessions invalidated successfully' }, - }, - }, - }) - @ApiStandardErrorResponse([401]) - @HttpCode(HttpStatus.OK) - async invalidateAllSessions(@Req() req: Request) { - const user = req['user'] as any; - await this.authService.invalidateAllSessions(user.id); - return { message: 'All sessions invalidated successfully' }; - } - - private getRequestMeta(req: Request): { ip: string; userAgent: string } { - const forwardedFor = req.headers['x-forwarded-for']; - const ip = Array.isArray(forwardedFor) - ? forwardedFor[0] - : forwardedFor?.toString().split(',')[0]?.trim() || req.ip || req.socket.remoteAddress || 'unknown'; - - return { - ip, - userAgent: Array.isArray(req.headers['user-agent']) - ? req.headers['user-agent'][0] - : req.headers['user-agent'] || 'unknown', - }; - } -} diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts deleted file mode 100644 index a2ee4200..00000000 --- a/src/auth/auth.module.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Module, forwardRef } from '@nestjs/common'; -import { JwtModule } from '@nestjs/jwt'; -import { PassportModule } from '@nestjs/passport'; -import { ConfigModule, ConfigService } from '@nestjs/config'; -import { AuthService } from './auth.service'; -import { AuthController } from './auth.controller'; -import { JwtStrategy } from './strategies/jwt.strategy'; -import { LocalStrategy } from './strategies/local.strategy'; -import { Web3Strategy } from './strategies/web3.strategy'; -import { JwtAuthGuard } from './guards/jwt-auth.guard'; -import { LoginAttemptsGuard } from './guards/login-attempts.guard'; -import { WalletSignatureService } from './wallet-signature.service'; -import { WalletSignatureGuard } from './guards/wallet-signature.guard'; -import { MfaModule } from './mfa/mfa.module'; -import { UsersModule } from '../users/users.module'; - -@Module({ - imports: [ - // FIX: Use forwardRef to break the circular dependency with UsersModule - forwardRef(() => UsersModule), - PassportModule, - JwtModule.registerAsync({ - imports: [ConfigModule], - inject: [ConfigService], - useFactory: (configService: ConfigService) => ({ - secret: configService.get('JWT_SECRET'), - signOptions: { - expiresIn: configService.get('JWT_EXPIRES_IN', '15m') as any, - }, - }), - }), - MfaModule, - ], - controllers: [AuthController], - providers: [ - AuthService, - JwtStrategy, - LocalStrategy, - Web3Strategy, - WalletSignatureService, - { - provide: 'JwtAuthGuard', - useClass: JwtAuthGuard, - }, - { - provide: 'LoginAttemptsGuard', - useClass: LoginAttemptsGuard, - }, - { - provide: 'WalletSignatureGuard', - useClass: WalletSignatureGuard, - }, - // NOTE: Removed UserService here because it's now imported via UsersModule - // NOTE: Removed RedisService as it's now globally provided by LoggingModule - ], - exports: [AuthService, WalletSignatureService], -}) -export class AuthModule {} diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts deleted file mode 100644 index f6bfb998..00000000 --- a/src/auth/auth.service.ts +++ /dev/null @@ -1,644 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { - UnauthorizedException, - InvalidCredentialsException, - TokenExpiredException, - InvalidInputException, - UserNotFoundException, -} from '../common/errors/custom.exceptions'; -import { UserService } from '../users/user.service'; -import { JwtService } from '@nestjs/jwt'; -import { ConfigService } from '@nestjs/config'; -import { CreateUserDto } from '../users/dto/create-user.dto'; -import * as bcrypt from 'bcrypt'; -import { RedisService } from '../common/services/redis.service'; -import { v4 as uuidv4 } from 'uuid'; -import { StructuredLoggerService } from '../common/logging/logger.service'; -import { JwtPayload, SessionInfo } from './auth.types'; -import { JWT_TOKEN_USE, tokenRevocationRedisKeys } from './constants'; -import { createHash } from 'crypto'; - -/** - * Auth Service - * - * Handles all authentication operations including: - * - User registration and email verification - * - Email/Password and Web3 wallet login - * - JWT Token generation and rotation - * - Session management and invalidation - * - * @class AuthService - */ -@Injectable() -export class AuthService { - constructor( - private readonly userService: UserService, - private readonly jwtService: JwtService, - private readonly configService: ConfigService, - private readonly redisService: RedisService, - private readonly logger: StructuredLoggerService, - ) { - this.logger.setContext('AuthService'); - } - - /** - * Register a new user and send verification email - * - * @param {CreateUserDto} createUserDto - The user registration data - * @returns {Promise<{message: string}>} Success message - * - * @example - * ```typescript - * const result = await authService.register({ - * email: 'dev@propchain.com', - * password: 'Password123!', - * firstName: 'Prop', - * lastName: 'Chain' - * }); - * ``` - */ - async register(createUserDto: CreateUserDto) { - try { - const user = await this.userService.create(createUserDto); - await this.sendVerificationEmail(user.id, user.email); - this.logger.logAuth('User registration successful', { userId: user.id }); - return { - message: 'User registered successfully. Please check your email for verification.', - }; - } catch (error: unknown) { - const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; - this.logger.error('User registration failed', errorMessage, { - email: createUserDto.email, - }); - throw error; - } - } - - /** - * Authenticate a user and generate JWT tokens - * - * Supports both email/password and Web3 wallet address/signature. - * Implements login attempt tracking for brute-force protection. - * - * @param {Object} credentials - The credentials to authenticate - * @param {Object} [requestMeta] - Request metadata for session fingerprinting - * @returns {Promise} The generated tokens and user info - * - * @example - * ```typescript - * // Email login - * const auth = await authService.login({ - * email: 'dev@propchain.com', - * password: 'Password123!' - * }); - * - * // Web3 login - * const auth = await authService.login({ - * walletAddress: '0x123...', - * signature: '0xabc...' - * }); - * ``` - */ - async login( - credentials: { email?: string; password?: string; walletAddress?: string; signature?: string }, - requestMeta?: { ip?: string; userAgent?: string }, - ) { - let user: any; - - // brute force protection - const identifier = credentials.email || credentials.walletAddress; - const maxAttempts = this.configService.get('MAX_LOGIN_ATTEMPTS', 5); - const attemptWindow = this.configService.get('LOGIN_ATTEMPT_WINDOW', 600); // seconds - const attemptsKey = identifier ? `login_attempts:${identifier}` : null; - - if (attemptsKey) { - const existing = await this.redisService.get(attemptsKey); - const attempts = parseInt(existing || '0', 10); - if (attempts >= maxAttempts) { - this.logger.warn('Too many login attempts', { identifier }); - throw new UnauthorizedException('Too many login attempts. Please try again later.'); - } - } - - try { - if (credentials.email && credentials.password) { - user = await this.validateUserByEmail(credentials.email, credentials.password); - } else if (credentials.walletAddress) { - user = await this.validateUserByWallet(credentials.walletAddress, credentials.signature); - } else { - throw new InvalidInputException(undefined, 'Email/password or wallet address/signature required'); - } - - if (!user) { - this.logger.warn('Invalid login attempt', { email: credentials.email }); - // increment attempt count only for email-based logins - if (attemptsKey) { - const existing = await this.redisService.get(attemptsKey); - const attempts = parseInt(existing || '0', 10) + 1; - await this.redisService.setex(attemptsKey, attemptWindow, attempts.toString()); - } - throw new InvalidCredentialsException(); - } - - // successful login, clear attempts - if (attemptsKey) { - await this.redisService.del(attemptsKey); - } - - this.logger.logAuth('User login successful', { userId: user.id }); - return this.generateTokens(user, requestMeta); - } catch (error: unknown) { - const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; - this.logger.error('User login failed', errorMessage, { - email: credentials.email, - }); - throw error; - } - } - - async validateUserByEmail(email: string, password: string): Promise { - const user = await this.userService.findByEmail(email); - - if (!user || !user.password) { - this.logger.warn('Email validation failed: User not found', { email }); - throw new InvalidCredentialsException(); - } - - const isPasswordValid = await bcrypt.compare(password, user.password as string); - if (!isPasswordValid) { - this.logger.warn('Email validation failed: Invalid password', { email }); - throw new InvalidCredentialsException(); - } - - const { password: _, ...result } = user as any; - return result; - } - - async validateUserByWallet(walletAddress: string, signature?: string): Promise { - let user = await this.userService.findByWalletAddress(walletAddress); - - if (!user) { - user = await this.userService.create({ - email: `${walletAddress}@wallet.auth`, - password: Math.random().toString(36).slice(-10), - walletAddress, - firstName: 'Web3', - lastName: 'User', - }); - this.logger.logAuth('New Web3 user created', { walletAddress }); - } - - const { password: _, ...result } = user as any; - return result; - } - - async refreshToken(refreshToken: string, requestMeta?: { ip?: string; userAgent?: string }) { - try { - const payload = (await this.jwtService.verifyAsync(refreshToken, { - secret: this.configService.get('JWT_REFRESH_SECRET'), - })) as JwtPayload; - - if (payload.tokenUse !== JWT_TOKEN_USE.REFRESH || !payload.rid) { - this.logger.warn('Refresh token validation failed: wrong token type', { userId: payload.sub }); - throw new TokenExpiredException('Invalid refresh token'); - } - - const user = (await this.userService.findById(payload.sub)) as { id: string; email: string; [key: string]: any }; - if (!user) { - this.logger.warn('Refresh token validation failed: User not found', { - userId: payload.sub, - }); - throw new UserNotFoundException(payload.sub); - } - - const refreshSessionData = await this.redisService.get(tokenRevocationRedisKeys.refreshSession(payload.rid)); - if (!refreshSessionData) { - this.logger.warn('Refresh token validation failed: missing refresh session', { userId: payload.sub }); - throw new TokenExpiredException('Invalid refresh token'); - } - - const refreshSession = JSON.parse(refreshSessionData) as { - userId: string; - sessionId: string; - fingerprint: string; - }; - const currentRid = await this.redisService.get(tokenRevocationRedisKeys.userRefreshSession(payload.sub)); - - if (refreshSession.userId !== payload.sub || currentRid !== payload.rid) { - this.logger.warn('Refresh token validation failed: revoked or rotated', { userId: payload.sub }); - throw new TokenExpiredException('Invalid refresh token'); - } - - const existingSession = await this.getSessionById(payload.sub, refreshSession.sessionId); - if (!existingSession) { - this.logger.warn('Refresh token validation failed: session missing', { userId: payload.sub }); - throw new TokenExpiredException('Invalid refresh token'); - } - - this.assertFingerprintMatches(existingSession, requestMeta); - await this.invalidateSession(payload.sub, refreshSession.sessionId); - - this.logger.logAuth('Token refreshed successfully', { userId: user.id }); - return this.generateTokens(user, requestMeta); - } catch (error) { - const stack = error instanceof Error ? error.stack : undefined; - this.logger.error('Token refresh failed', stack); - throw new TokenExpiredException('Invalid refresh token'); - } - } - - async logout(userId: string, accessToken?: string) { - // Blacklist the current access token - if (accessToken) { - const tokenPayload = await this.jwtService.decode(accessToken); - if (tokenPayload && typeof tokenPayload === 'object' && 'jti' in tokenPayload) { - const jti = tokenPayload.jti; - const expiry = tokenPayload.exp; - if (jti && expiry) { - const ttl = expiry - Math.floor(Date.now() / 1000); - if (ttl > 0) { - await this.redisService.setex(tokenRevocationRedisKeys.accessRevoked(jti), ttl, userId); - this.logger.logAuth('Access token blacklisted', { userId, jti }); - } - } - } - } - - // === REFRESH TOKEN REVOCATION === - // Prevents token refresh even if JWT signature is still valid - - if (accessToken) { - const tokenPayload = this.jwtService.decode(accessToken) as JwtPayload | null; - if (tokenPayload?.sid) { - await this.invalidateSession(userId, tokenPayload.sid); - } - } else { - await this.clearRefreshSessionForUser(userId); - } - this.logger.logAuth('User logged out successfully', { userId }); - return { message: 'Logged out successfully' }; - } - - async forgotPassword(email: string) { - const user = (await this.userService.findByEmail(email)) as { - id: string; - email: string; - [key: string]: any; - } | null; - if (!user) { - this.logger.log('Forgot password request for non-existent user', { email }); - return { message: 'If email exists, a reset link has been sent' }; - } - - const resetToken = uuidv4(); - const resetTokenExpiry = Date.now() + 3600000; // 1 hour - - // Save reset token and expiry in Redis - await this.redisService.set( - `password_reset:${resetToken}`, - JSON.stringify({ userId: user.id, expiry: resetTokenExpiry }), - ); - - await this.sendPasswordResetEmail(user.email, resetToken); - this.logger.log('Password reset email sent', { email }); - return { message: 'If email exists, a reset link has been sent' }; - } - - async resetPassword(resetToken: string, newPassword: string) { - const resetData = await this.redisService.get(`password_reset:${resetToken}`); - - if (!resetData) { - this.logger.warn('Invalid or expired password reset token received'); - throw new InvalidInputException(undefined, 'Invalid or expired reset token'); - } - - const { userId, expiry } = JSON.parse(resetData); - - if (Date.now() > expiry) { - await this.redisService.del(`password_reset:${resetToken}`); - this.logger.warn('Expired password reset token used', { userId }); - throw new InvalidInputException(undefined, 'Reset token has expired'); - } - - await this.userService.updatePassword(userId, newPassword); - await this.redisService.del(`password_reset:${resetToken}`); - await this.invalidateAllSessions(userId); - - this.logger.log('Password reset successfully', { userId }); - return { message: 'Password reset successfully' }; - } - - async verifyEmail(token: string) { - const verificationData = await this.redisService.get(`email_verification:${token}`); - - if (!verificationData) { - this.logger.warn('Invalid or expired email verification token'); - throw new InvalidInputException(undefined, 'Invalid or expired verification token'); - } - - const { userId } = JSON.parse(verificationData); - await this.userService.verifyUser(userId); - await this.redisService.del(`email_verification:${token}`); - - this.logger.log('Email verified successfully', { userId }); - return { message: 'Email verified successfully' }; - } - - /** - * Access-token revocation list (Redis). Entries use TTL so the key expires with the JWT. - */ - async isTokenBlacklisted(jti: string): Promise { - const blacklisted = await this.redisService.get(tokenRevocationRedisKeys.accessRevoked(jti)); - return blacklisted !== null; - } - - async getActiveSessions(userId: string): Promise { - const sessionKeys = await this.redisService.keys(`active_session:${userId}:*`); - const sessions = []; - - for (const key of sessionKeys) { - const sessionData = await this.redisService.get(key); - if (sessionData) { - sessions.push(JSON.parse(sessionData)); - } - } - - return sessions; - } - - async getSessionById(userId: string, sessionId: string): Promise { - const sessionData = await this.redisService.get(tokenRevocationRedisKeys.activeSession(userId, sessionId)); - return sessionData ? JSON.parse(sessionData) : null; - } - - async getAllUserSessions(userId: string): Promise { - const sessions = await this.getActiveSessions(userId); - return sessions.map(session => ({ - ...session, - isActive: true, - expiresIn: this.getSessionExpiry(session.lastActivity || session.createdAt), - })); - } - - async invalidateAllSessions(userId: string): Promise { - const sessionKeys = await this.redisService.keys(`active_session:${userId}:*`); - for (const key of sessionKeys) { - const sessionData = await this.redisService.get(key); - if (sessionData) { - const session = JSON.parse(sessionData) as SessionInfo; - await this.redisService.del(tokenRevocationRedisKeys.accessSession(session.jti)); - await this.redisService.del(tokenRevocationRedisKeys.refreshSession(session.refreshSessionId)); - } - await this.redisService.del(key); - } - await this.clearRefreshSessionForUser(userId); - this.logger.logAuth('All sessions invalidated', { userId }); - } - - async getConcurrentSessions(userId: string): Promise { - const sessions = await this.getActiveSessions(userId); - return sessions.length; - } - - private getSessionExpiry(createdAt: string): number { - const created = new Date(createdAt); - const sessionTimeout = this.configService.get('SESSION_TIMEOUT', 3600) * 1000; - const expiry = created.getTime() + sessionTimeout; - return Math.max(0, expiry - Date.now()); - } - - async invalidateSession(userId: string, sessionId: string): Promise { - const session = await this.getSessionById(userId, sessionId); - if (session) { - await this.redisService.del(tokenRevocationRedisKeys.accessSession(session.jti)); - await this.redisService.del(tokenRevocationRedisKeys.refreshSession(session.refreshSessionId)); - const currentRid = await this.redisService.get(tokenRevocationRedisKeys.userRefreshSession(userId)); - if (currentRid === session.refreshSessionId) { - await this.redisService.del(tokenRevocationRedisKeys.userRefreshSession(userId)); - } - const ttl = this.getSessionExpiry(session.lastActivity || session.createdAt); - if (ttl > 0) { - await this.redisService.setex( - tokenRevocationRedisKeys.accessRevoked(session.jti), - Math.ceil(ttl / 1000), - userId, - ); - } - } - await this.redisService.del(tokenRevocationRedisKeys.activeSession(userId, sessionId)); - this.logger.logAuth('Session invalidated', { userId, sessionId }); - } - - async validateActiveSession( - userId: string, - jti: string, - sessionId: string, - requestMeta?: { ip?: string; userAgent?: string }, - ): Promise { - const mappedSessionId = await this.redisService.get(tokenRevocationRedisKeys.accessSession(jti)); - if (!mappedSessionId || mappedSessionId !== sessionId) { - throw new UnauthorizedException('Session is no longer active'); - } - - const session = await this.getSessionById(userId, sessionId); - if (!session || session.jti !== jti) { - throw new UnauthorizedException('Session is no longer active'); - } - - const absoluteExpiry = session.absoluteExpiresAt ? new Date(session.absoluteExpiresAt).getTime() : 0; - if (absoluteExpiry && absoluteExpiry <= Date.now()) { - await this.invalidateSession(userId, sessionId); - throw new UnauthorizedException('Session has expired'); - } - - this.assertFingerprintMatches(session, requestMeta); - - const idleTimeoutSeconds = this.configService.get('SESSION_TIMEOUT', 3600); - const lastActivity = new Date(session.lastActivity || session.createdAt).getTime(); - if (Date.now() - lastActivity > idleTimeoutSeconds * 1000) { - await this.invalidateSession(userId, sessionId); - throw new UnauthorizedException('Session has expired'); - } - - const updatedSession: SessionInfo = { - ...session, - lastActivity: new Date().toISOString(), - ip: requestMeta?.ip || session.ip, - userAgent: requestMeta?.userAgent || session.userAgent, - }; - - await this.persistSession(updatedSession); - return updatedSession; - } - - private async clearRefreshSessionForUser(userId: string): Promise { - const rid = await this.redisService.get(tokenRevocationRedisKeys.userRefreshSession(userId)); - if (rid) { - await this.redisService.del(tokenRevocationRedisKeys.refreshSession(rid)); - } - await this.redisService.del(tokenRevocationRedisKeys.userRefreshSession(userId)); - } - - private refreshSessionTtlSeconds(refreshToken: string): number { - const decoded = this.jwtService.decode(refreshToken) as { exp?: number } | null; - if (!decoded?.exp) { - return 0; - } - return Math.max(0, decoded.exp - Math.floor(Date.now() / 1000)); - } - - private async generateTokens(user: any, requestMeta?: { ip?: string; userAgent?: string }) { - await this.clearRefreshSessionForUser(user.id); - - const jti = uuidv4(); - const sessionId = uuidv4(); - const refreshSessionId = uuidv4(); - - const accessPayload: JwtPayload = { - sub: user.id, - email: user.email, - jti, - sid: sessionId, - tokenUse: JWT_TOKEN_USE.ACCESS, - }; - - const refreshPayload: JwtPayload = { - sub: user.id, - email: user.email, - sid: sessionId, - rid: refreshSessionId, - tokenUse: JWT_TOKEN_USE.REFRESH, - }; - - const accessToken = this.jwtService.sign(accessPayload, { - secret: this.configService.get('JWT_SECRET'), - expiresIn: this.configService.get('JWT_EXPIRES_IN', '15m') as any, - }); - - const refreshToken = this.jwtService.sign(refreshPayload, { - secret: this.configService.get('JWT_REFRESH_SECRET'), - expiresIn: this.configService.get('JWT_REFRESH_EXPIRES_IN', '7d') as any, - }); - - let refreshTtl = this.refreshSessionTtlSeconds(refreshToken); - if (refreshTtl <= 0) { - refreshTtl = 7 * 24 * 60 * 60; - } - const sessionMeta = this.buildSessionInfo(user.id, sessionId, jti, refreshSessionId, requestMeta); - await this.redisService.setex( - tokenRevocationRedisKeys.refreshSession(refreshSessionId), - refreshTtl, - JSON.stringify({ - userId: user.id, - sessionId, - fingerprint: sessionMeta.fingerprint, - }), - ); - await this.redisService.setex(tokenRevocationRedisKeys.userRefreshSession(user.id), refreshTtl, refreshSessionId); - - const sessionExpiry = this.configService.get('SESSION_TIMEOUT', 3600); - await this.redisService.setex(tokenRevocationRedisKeys.accessSession(jti), sessionExpiry, sessionId); - await this.persistSession(sessionMeta); - - this.logger.debug('Generated new tokens for user', { userId: user.id, jti, refreshSessionId, sessionId }); - - return { - access_token: accessToken, - refresh_token: refreshToken, - user: { - id: user.id, - email: user.email, - walletAddress: user.walletAddress, - isVerified: user.isVerified, - }, - }; - } - - private async sendVerificationEmail(userId: string, email: string) { - const verificationToken = uuidv4(); - - // Save token in Redis - const expiry = Date.now() + 3600000; // 1 hour - await this.redisService.set(`email_verification:${verificationToken}`, JSON.stringify({ userId, expiry })); - - // Import EmailService and send actual email - const { EmailService } = await import('../communication/email/email.service'); - const emailService = new EmailService(this.configService, null, null, null); - - await emailService.sendTemplatedEmail(email, 'email-verification', { - firstName: email.split('@')[0], // Extract name from email for personalization - verificationUrl: `${this.configService.get('BASE_URL')}/auth/verify-email/${verificationToken}`, - }); - - this.logger.log(`Verification email sent to ${email}`, { userId }); - this.logger.debug(`Verification token generated for ${email}`, { userId }); - } - - private async sendPasswordResetEmail(email: string, resetToken: string) { - // Import EmailService and send actual email - const { EmailService } = await import('../communication/email/email.service'); - const emailService = new EmailService(this.configService, null, null, null); - - await emailService.sendTemplatedEmail(email, 'password-reset', { - firstName: email.split('@')[0], // Extract name from email for personalization - resetUrl: `${this.configService.get('BASE_URL')}/auth/reset-password/${resetToken}`, - }); - - this.logger.log(`Password reset email sent to ${email}`); - this.logger.debug(`Password reset token generated for ${email}`); - } - - private buildSessionInfo( - userId: string, - sessionId: string, - jti: string, - refreshSessionId: string, - requestMeta?: { ip?: string; userAgent?: string }, - ): SessionInfo { - const now = new Date(); - const absoluteLifetimeSeconds = this.configService.get('SESSION_ABSOLUTE_TIMEOUT', 86400); - - return { - sessionId, - userId, - jti, - refreshSessionId, - createdAt: now.toISOString(), - lastActivity: now.toISOString(), - userAgent: requestMeta?.userAgent || 'unknown', - ip: requestMeta?.ip || 'unknown', - absoluteExpiresAt: new Date(now.getTime() + absoluteLifetimeSeconds * 1000).toISOString(), - fingerprint: this.buildFingerprint(requestMeta), - }; - } - - private async persistSession(session: SessionInfo): Promise { - const sessionExpiry = this.configService.get('SESSION_TIMEOUT', 3600); - await this.redisService.setex( - tokenRevocationRedisKeys.activeSession(session.userId, session.sessionId), - sessionExpiry, - JSON.stringify(session), - ); - await this.redisService.setex( - tokenRevocationRedisKeys.accessSession(session.jti), - sessionExpiry, - session.sessionId, - ); - } - - private buildFingerprint(requestMeta?: { ip?: string; userAgent?: string }): string { - const source = `${requestMeta?.ip || 'unknown'}|${requestMeta?.userAgent || 'unknown'}`; - return createHash('sha256').update(source).digest('hex'); - } - - private assertFingerprintMatches(session: SessionInfo, requestMeta?: { ip?: string; userAgent?: string }): void { - if (!session.fingerprint) { - return; - } - - const requestFingerprint = this.buildFingerprint(requestMeta); - if (requestFingerprint !== session.fingerprint) { - throw new UnauthorizedException('Session validation failed'); - } - } -} diff --git a/src/auth/auth.types.ts b/src/auth/auth.types.ts deleted file mode 100644 index 0a1ab7df..00000000 --- a/src/auth/auth.types.ts +++ /dev/null @@ -1,124 +0,0 @@ -// Authentication type definitions - -export interface AuthUser { - id: string; - email: string; - walletAddress?: string; - password?: string; - firstName?: string; - lastName?: string; - isVerified: boolean; - role: string; - createdAt: Date; - updatedAt: Date; -} - -export interface JwtPayload { - sub: string; - email: string; - jti?: string; - sid?: string; - /** Refresh rotation id; present only on refresh JWTs. */ - rid?: string; - /** Distinguishes access vs refresh tokens when both are JWTs. */ - tokenUse?: 'access' | 'refresh'; - iat?: number; - exp?: number; -} - -export interface AuthTokens { - access_token: string; - refresh_token: string; - user: { - id: string; - email: string; - walletAddress?: string; - isVerified: boolean; - }; -} - -export interface LoginRequest { - email: string; - password: string; -} - -export interface Web3LoginRequest { - walletAddress: string; - signature: string; -} - -export interface RefreshTokenRequest { - refresh_token: string; -} - -export interface RegisterRequest { - email: string; - password: string; - firstName?: string; - lastName?: string; - walletAddress?: string; -} - -export interface PasswordResetRequest { - email: string; -} - -export interface PasswordResetConfirmRequest { - token: string; - newPassword: string; -} - -export interface MfaSetupRequest { - method: 'totp' | 'sms' | 'email'; - phoneNumber?: string; - email?: string; -} - -export interface MfaVerifyRequest { - method: string; - code: string; -} - -export interface SessionInfo { - sessionId: string; - userId: string; - jti: string; - refreshSessionId: string; - createdAt: string; - userAgent: string; - ip: string; - lastActivity?: string; - absoluteExpiresAt?: string; - fingerprint?: string; -} - -export interface LoginAttempt { - email: string; - ip: string; - timestamp: Date; - success: boolean; - userAgent?: string; -} - -export interface AccountLockInfo { - email: string; - ip: string; - lockoutUntil: Date; - failedAttempts: number; - lastAttempt: Date; -} - -export interface TokenBlacklistEntry { - jti: string; - userId: string; - blacklistedAt: Date; - reason?: string; -} - -export interface AuthRequestContext { - user?: AuthUser; - session?: SessionInfo; - ip: string; - userAgent: string; - timestamp: Date; -} diff --git a/src/auth/constants.ts b/src/auth/constants.ts deleted file mode 100644 index 31c244a0..00000000 --- a/src/auth/constants.ts +++ /dev/null @@ -1,20 +0,0 @@ -export const jwtConstants = { - secret: process.env.JWT_SECRET || 'default_secret_for_development', -}; - -/** Access vs refresh JWT claim; prevents using an access JWT on the refresh endpoint. */ -export const JWT_TOKEN_USE = { - ACCESS: 'access', - REFRESH: 'refresh', -} as const; - -/** - * Redis keys for token revocation: access-token denylist (by jti) and refresh rotation (by session id). - */ -export const tokenRevocationRedisKeys = { - accessRevoked: (jti: string) => `blacklisted_token:${jti}`, - refreshSession: (refreshSessionId: string) => `refresh_session:${refreshSessionId}`, - userRefreshSession: (userId: string) => `user_refresh_rid:${userId}`, - activeSession: (userId: string, sessionId: string) => `active_session:${userId}:${sessionId}`, - accessSession: (jti: string) => `access_session:${jti}`, -} as const; diff --git a/src/auth/decorators/roles.decorator.ts b/src/auth/decorators/roles.decorator.ts deleted file mode 100644 index dcb35007..00000000 --- a/src/auth/decorators/roles.decorator.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { SetMetadata } from '@nestjs/common'; -import { RequiredRoles } from '../guards/rbac.guard'; - -export const Roles = (resource: string, action: string) => SetMetadata('roles', { resource, action }); diff --git a/src/auth/dto/auth-response.dto.ts b/src/auth/dto/auth-response.dto.ts deleted file mode 100644 index 6b92d3af..00000000 --- a/src/auth/dto/auth-response.dto.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; -import { Exclude, Expose, Type } from 'class-transformer'; -import { IsString, IsOptional, IsNumber, IsArray, IsEmail, ValidateNested, ArrayMinSize } from 'class-validator'; - -@Exclude() -export class TokenPairDto { - @Expose() - @ApiProperty({ - description: 'JWT access token', - example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', - }) - @IsString() - accessToken: string; - - @Expose() - @ApiProperty({ - description: 'JWT refresh token', - example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', - }) - @IsString() - refreshToken: string; - - @Expose() - @ApiProperty({ - description: 'Token expiration time in seconds', - example: 3600, - }) - @IsNumber() - expiresIn: number; - - @Expose() - @ApiProperty({ - description: 'Token type', - example: 'Bearer', - }) - @IsString() - tokenType: string; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} - -@Exclude() -export class AuthUserDto { - @Expose() - @ApiProperty({ example: 'user_abc123' }) - @IsString() - id: string; - - @Expose() - @ApiProperty({ example: 'john.doe@example.com' }) - @IsEmail() - email: string; - - @Expose() - @ApiPropertyOptional({ example: 'John' }) - @IsOptional() - @IsString() - firstName?: string; - - @Expose() - @ApiPropertyOptional({ example: 'Doe' }) - @IsOptional() - @IsString() - lastName?: string; - - @Expose() - @ApiPropertyOptional({ example: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e' }) - @IsOptional() - @IsString() - walletAddress?: string; - - @Expose() - @ApiProperty({ example: ['user'] }) - @IsArray() - @ArrayMinSize(1) - @IsString({ each: true }) - roles: string[]; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} - -@Exclude() -export class LoginResponseDto { - @Expose() - @ApiProperty({ type: AuthUserDto }) - @ValidateNested() - @Type(() => AuthUserDto) - user: AuthUserDto; - - @Expose() - @ApiProperty({ type: TokenPairDto }) - @ValidateNested() - @Type(() => TokenPairDto) - tokens: TokenPairDto; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} - -@Exclude() -export class RegisterResponseDto { - @Expose() - @ApiProperty({ type: AuthUserDto }) - @ValidateNested() - @Type(() => AuthUserDto) - user: AuthUserDto; - - @Expose() - @ApiProperty({ - description: 'Message about email verification', - example: 'Please check your email to verify your account', - }) - @IsString() - message: string; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} - -@Exclude() -export class MessageResponseDto { - @Expose() - @ApiProperty({ - description: 'Response message', - example: 'Operation completed successfully', - }) - @IsString() - message: string; - - constructor(partial: Partial) { - Object.assign(this, partial); - } -} diff --git a/src/auth/dto/forgot-password.dto.ts b/src/auth/dto/forgot-password.dto.ts deleted file mode 100644 index 60d0d35b..00000000 --- a/src/auth/dto/forgot-password.dto.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { IsEmail, IsNotEmpty } from 'class-validator'; -import { ApiProperty } from '@nestjs/swagger'; - -export class ForgotPasswordDto { - @ApiProperty({ - description: 'Email address to send password reset link', - example: 'john.doe@example.com', - }) - @IsEmail({}, { message: 'Please provide a valid email address' }) - @IsNotEmpty({ message: 'Email is required' }) - email: string; -} diff --git a/src/auth/dto/index.ts b/src/auth/dto/index.ts deleted file mode 100644 index 88e3ac0e..00000000 --- a/src/auth/dto/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export * from './login.dto'; -export * from './refresh-token.dto'; -export * from './forgot-password.dto'; -export * from './reset-password.dto'; -export * from './verify-email-params.dto'; -export * from './auth-response.dto'; diff --git a/src/auth/dto/login.dto.ts b/src/auth/dto/login.dto.ts deleted file mode 100644 index d9f59cc1..00000000 --- a/src/auth/dto/login.dto.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { IsEmail, IsString, IsNotEmpty, ValidateIf } from 'class-validator'; -import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; -import { IsEthereumAddress } from '../../common/validators'; - -/** - * DTO for email/password login - */ -export class LoginEmailDto { - @ApiProperty({ - description: 'User email address', - example: 'john.doe@example.com', - }) - @IsEmail({}, { message: 'Please provide a valid email address' }) - @IsNotEmpty({ message: 'Email is required' }) - email: string; - - @ApiProperty({ - description: 'User password', - example: 'SecureP@ss123', - minLength: 8, - }) - @IsString({ message: 'Password must be a string' }) - @IsNotEmpty({ message: 'Password is required' }) - password: string; -} - -/** - * DTO for Web3 wallet login - */ -export class LoginWeb3Dto { - @ApiProperty({ - description: 'Ethereum wallet address', - example: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', - }) - @IsEthereumAddress({ message: 'Invalid Ethereum wallet address' }) - @IsNotEmpty({ message: 'Wallet address is required' }) - walletAddress: string; - - @ApiProperty({ - description: 'Signature from wallet for authentication', - example: '0x...', - }) - @IsString({ message: 'Signature must be a string' }) - @IsNotEmpty({ message: 'Signature is required' }) - signature: string; -} - -/** - * Combined DTO for backward compatibility - supports both email and Web3 login - * Uses conditional validation based on which fields are provided - */ -export class LoginDto { - @ApiPropertyOptional({ - description: 'User email address (required for email login)', - example: 'john.doe@example.com', - }) - @ValidateIf(o => !o.walletAddress) - @IsEmail({}, { message: 'Please provide a valid email address' }) - @IsNotEmpty({ message: 'Email is required when not using Web3 login' }) - email?: string; - - @ApiPropertyOptional({ - description: 'User password (required for email login)', - example: 'SecureP@ss123', - }) - @ValidateIf(o => !o.walletAddress) - @IsString({ message: 'Password must be a string' }) - @IsNotEmpty({ message: 'Password is required when not using Web3 login' }) - password?: string; - - @ApiPropertyOptional({ - description: 'Ethereum wallet address (required for Web3 login)', - example: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', - }) - @ValidateIf(o => !o.email) - @IsEthereumAddress({ message: 'Invalid Ethereum wallet address' }) - @IsNotEmpty({ message: 'Wallet address is required for Web3 login' }) - walletAddress?: string; - - @ApiPropertyOptional({ - description: 'Signature from wallet (required for Web3 login)', - example: '0x...', - }) - @ValidateIf(o => !o.email) - @IsString({ message: 'Signature must be a string' }) - @IsNotEmpty({ message: 'Signature is required for Web3 login' }) - signature?: string; -} diff --git a/src/auth/dto/refresh-token.dto.ts b/src/auth/dto/refresh-token.dto.ts deleted file mode 100644 index bc63480f..00000000 --- a/src/auth/dto/refresh-token.dto.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { IsString, IsNotEmpty, IsJWT } from 'class-validator'; -import { ApiProperty } from '@nestjs/swagger'; - -export class RefreshTokenDto { - @ApiProperty({ - description: 'JWT refresh token', - example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', - }) - @IsString({ message: 'Refresh token must be a string' }) - @IsNotEmpty({ message: 'Refresh token is required' }) - @IsJWT({ message: 'Invalid refresh token format' }) - refreshToken: string; -} diff --git a/src/auth/dto/reset-password.dto.ts b/src/auth/dto/reset-password.dto.ts deleted file mode 100644 index 7e040468..00000000 --- a/src/auth/dto/reset-password.dto.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { IsString, IsNotEmpty, MinLength, MaxLength } from 'class-validator'; -import { ApiProperty } from '@nestjs/swagger'; -import { IsStrongPassword } from '../../common/validators'; - -export class ResetPasswordDto { - @ApiProperty({ - description: 'Password reset token received via email', - example: 'abc123def456...', - }) - @IsString({ message: 'Token must be a string' }) - @IsNotEmpty({ message: 'Reset token is required' }) - token: string; - - @ApiProperty({ - description: 'New password (min 8 chars, 1 uppercase, 1 lowercase, 1 number, 1 special char)', - example: 'NewSecureP@ss123', - minLength: 8, - }) - @IsString({ message: 'Password must be a string' }) - @IsNotEmpty({ message: 'New password is required' }) - @MinLength(8, { message: 'Password must be at least 8 characters' }) - @MaxLength(128, { message: 'Password must not exceed 128 characters' }) - @IsStrongPassword() - newPassword: string; -} diff --git a/src/auth/dto/verify-email-params.dto.ts b/src/auth/dto/verify-email-params.dto.ts deleted file mode 100644 index 6b313147..00000000 --- a/src/auth/dto/verify-email-params.dto.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { IsString, IsNotEmpty } from 'class-validator'; -import { ApiProperty } from '@nestjs/swagger'; - -export class VerifyEmailParamsDto { - @ApiProperty({ - description: 'Email verification token', - example: 'verification_token_abc123', - }) - @IsString({ message: 'Token must be a string' }) - @IsNotEmpty({ message: 'Verification token is required' }) - token: string; -} diff --git a/src/auth/guards/jwt-auth.guard.ts b/src/auth/guards/jwt-auth.guard.ts deleted file mode 100644 index 67c9865e..00000000 --- a/src/auth/guards/jwt-auth.guard.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Injectable, UnauthorizedException } from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { AuthService } from '../auth.service'; - -@Injectable() -export class JwtAuthGuard extends AuthGuard('jwt') { - constructor(private readonly authService: AuthService) { - super(); - } - - override async canActivate(context: any): Promise { - const result = (await super.canActivate(context)) as boolean; - - if (result) { - const request = context.switchToHttp().getRequest(); - const user = request.user; - - // Check if token is blacklisted - if (user && user.jti) { - const isBlacklisted = await this.authService.isTokenBlacklisted(user.jti); - if (isBlacklisted) { - throw new UnauthorizedException('Token has been revoked'); - } - } - - if (user?.id && user?.jti && user?.sid) { - request.session = await this.authService.validateActiveSession(user.id, user.jti, user.sid, { - ip: request.ip || request.socket?.remoteAddress || 'unknown', - userAgent: request.headers['user-agent'] || 'unknown', - }); - } else { - throw new UnauthorizedException('Invalid session context'); - } - } - - return result; - } -} diff --git a/src/auth/guards/local-auth.guard.ts b/src/auth/guards/local-auth.guard.ts deleted file mode 100644 index ccf962b6..00000000 --- a/src/auth/guards/local-auth.guard.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; - -@Injectable() -export class LocalAuthGuard extends AuthGuard('local') {} diff --git a/src/auth/guards/login-attempts.guard.ts b/src/auth/guards/login-attempts.guard.ts deleted file mode 100644 index 3857a8fd..00000000 --- a/src/auth/guards/login-attempts.guard.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { Injectable, UnauthorizedException } from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; -import { RedisService } from '../../common/services/redis.service'; -import { ConfigService } from '@nestjs/config'; -import { StructuredLoggerService } from '../../common/logging/logger.service'; - -@Injectable() -export class LoginAttemptsGuard extends AuthGuard('local') { - constructor( - private readonly redisService: RedisService, - private readonly configService: ConfigService, - private readonly logger: StructuredLoggerService, - ) { - super(); - this.logger.setContext('LoginAttemptsGuard'); - } - - async canActivate(context: any): Promise { - const request = context.switchToHttp().getRequest(); - const { email } = request.body; - const ip = this.getClientIp(request); - - if (!email) { - return false; - } - - // Check if account is locked - const isLocked = await this.isAccountLocked(email, ip); - if (isLocked) { - this.logger.warn('Login attempt blocked - account locked', { email, ip }); - throw new UnauthorizedException('Account temporarily locked due to too many failed attempts'); - } - - try { - const result = (await super.canActivate(context)) as boolean; - - if (result) { - // Successful login - reset attempt counters - await this.resetLoginAttempts(email, ip); - this.logger.logAuth('Successful login', { email, ip }); - } - - return result; - } catch (error) { - // Failed login - increment attempt counters - await this.recordFailedAttempt(email, ip); - this.logger.warn('Failed login attempt', { email, ip }); - throw error; - } - } - - private async isAccountLocked(email: string, ip: string): Promise { - const maxAttempts = this.configService.get('LOGIN_MAX_ATTEMPTS', 5); - const lockoutDuration = this.configService.get('LOGIN_LOCKOUT_DURATION', 900); - - // Check email-based attempts - const emailAttempts = await this.getLoginAttempts(`login_attempts:${email}`); - if (emailAttempts >= maxAttempts) { - return true; - } - - // Check IP-based attempts - const ipAttempts = await this.getLoginAttempts(`login_attempts:ip:${ip}`); - if (ipAttempts >= maxAttempts) { - return true; - } - - return false; - } - - private async recordFailedAttempt(email: string, ip: string): Promise { - const lockoutDuration = this.configService.get('LOGIN_LOCKOUT_DURATION', 900); - - // Increment email attempts - await this.incrementLoginAttempts(`login_attempts:${email}`, lockoutDuration); - - // Increment IP attempts - await this.incrementLoginAttempts(`login_attempts:ip:${ip}`, lockoutDuration); - } - - private async resetLoginAttempts(email: string, ip: string): Promise { - await this.redisService.del(`login_attempts:${email}`); - await this.redisService.del(`login_attempts:ip:${ip}`); - } - - private async getLoginAttempts(key: string): Promise { - const attempts = await this.redisService.get(key); - return attempts ? parseInt(attempts, 10) : 0; - } - - private async incrementLoginAttempts(key: string, expirySeconds: number): Promise { - const current = await this.getLoginAttempts(key); - await this.redisService.setex(key, expirySeconds, (current + 1).toString()); - } - - private getClientIp(request: any): string { - return request.ips?.length ? request.ips[0] : request.ip; - } -} diff --git a/src/auth/guards/rbac.guard.ts b/src/auth/guards/rbac.guard.ts deleted file mode 100644 index 66d3fa74..00000000 --- a/src/auth/guards/rbac.guard.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; -import { Reflector } from '@nestjs/core'; - -export interface RequiredRoles { - resource: string; - action: string; -} - -@Injectable() -export class RbacGuard implements CanActivate { - constructor(private reflector: Reflector) {} - - canActivate(context: ExecutionContext): boolean { - const requiredRoles = this.reflector.getAllAndOverride('roles', [ - context.getHandler(), - context.getClass(), - ]); - - if (!requiredRoles) { - return true; - } - - const { user } = context.switchToHttp().getRequest(); - - // Check if user has required permissions based on their roles - if (user.roles && user.roles.length > 0) { - // In a real implementation, you would check the user's permissions against the required roles - // For now, we'll implement a basic check - - // Example: check if user has admin role or appropriate permissions - const hasPermission = user.roles.some((role: any) => { - // This is a simplified check - in a real implementation you'd check against actual permissions - return role.name === 'ADMIN' || this.checkUserPermissions(user, requiredRoles); - }); - - return hasPermission; - } - - return false; - } - - private checkUserPermissions(user: any, requiredRoles: RequiredRoles): boolean { - // This would check the user's actual permissions against the required roles - // Implementation would depend on your specific RBAC model - return true; // Simplified for now - } -} diff --git a/src/auth/guards/throttle-auth.guard.ts b/src/auth/guards/throttle-auth.guard.ts deleted file mode 100644 index 26de4570..00000000 --- a/src/auth/guards/throttle-auth.guard.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ThrottlerGuard } from '@nestjs/throttler'; -import { Injectable } from '@nestjs/common'; - -@Injectable() -export class ThrottlerBehindProxyGuard extends ThrottlerGuard { - protected async getTracker(req: Record): Promise { - return req.ips.length ? req.ips[0] : req.ip; - } -} diff --git a/src/auth/guards/wallet-signature.guard.ts b/src/auth/guards/wallet-signature.guard.ts deleted file mode 100644 index 446b77ac..00000000 --- a/src/auth/guards/wallet-signature.guard.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Injectable, ExecutionContext, UnauthorizedException } from '@nestjs/common'; -import { Reflector } from '@nestjs/core'; -import { WalletSignatureService } from './wallet-signature.service'; - -/** - * Wallet Signature Guard - * - * Protects endpoints by requiring valid wallet signature verification. - * This guard addresses issue #270 by ensuring wallet ownership is verified. - */ -@Injectable() -export class WalletSignatureGuard { - constructor( - private readonly walletSignatureService: WalletSignatureService, - private readonly reflector: Reflector, - ) {} - - async canActivate(context: ExecutionContext): Promise { - const request = context.switchToHttp().getRequest(); - const user = request.user; - - if (!user) { - throw new UnauthorizedException('User not authenticated'); - } - - // Check if user has a wallet address - if (!user.walletAddress) { - throw new UnauthorizedException('User must have a wallet address for this operation'); - } - - // Verify wallet ownership using signature - try { - this.walletSignatureService.verifyWalletOwnership(request, user.walletAddress); - return true; - } catch (error) { - throw new UnauthorizedException('Invalid wallet signature'); - } - } -} diff --git a/src/auth/interceptors/security.interceptor.ts b/src/auth/interceptors/security.interceptor.ts deleted file mode 100644 index 90276905..00000000 --- a/src/auth/interceptors/security.interceptor.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common'; -import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; - -@Injectable() -export class SecurityInterceptor implements NestInterceptor { - intercept(context: ExecutionContext, next: CallHandler): Observable { - return next.handle().pipe( - map(data => { - // Sanitize response data to remove sensitive information - if (data && typeof data === 'object') { - // Remove password fields from responses - if (data.password) { - delete data.password; - } - - // If it's an array, sanitize each item - if (Array.isArray(data)) { - return data.map(item => { - if (item && typeof item === 'object' && item.password) { - const { password, ...sanitized } = item; - return sanitized; - } - return item; - }); - } - } - - return data; - }), - ); - } -} diff --git a/src/auth/mfa/index.ts b/src/auth/mfa/index.ts deleted file mode 100644 index 2102a95e..00000000 --- a/src/auth/mfa/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './mfa.service'; -export * from './mfa.controller'; -export * from './mfa.module'; diff --git a/src/auth/mfa/mfa.controller.ts b/src/auth/mfa/mfa.controller.ts deleted file mode 100644 index 99f098b2..00000000 --- a/src/auth/mfa/mfa.controller.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { Controller, Post, Get, Delete, Body, Req, UseGuards, HttpCode, HttpStatus } from '@nestjs/common'; -import { MfaService } from './mfa.service'; -import { JwtAuthGuard } from '../guards/jwt-auth.guard'; -import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; -import { Request } from 'express'; -import { SensitiveEndpointRateLimitGuard } from '../../security/guards/sensitive-endpoint-rate-limit.guard'; -import { SensitiveRateLimit } from '../../security/decorators/sensitive-rate-limit.decorator'; - -@ApiTags('mfa') -@Controller('mfa') -export class MfaController { - constructor(private readonly mfaService: MfaService) {} - - @Post('setup') - @UseGuards(JwtAuthGuard) - @ApiOperation({ summary: 'Generate MFA setup QR code' }) - @ApiResponse({ status: 200, description: 'MFA setup initiated successfully.' }) - @HttpCode(HttpStatus.OK) - async setupMfa(@Req() req: Request) { - const user = req['user'] as any; - return this.mfaService.generateMfaSecret(user.id, user.email); - } - - @Post('verify') - @UseGuards(JwtAuthGuard, SensitiveEndpointRateLimitGuard) - @SensitiveRateLimit({ - windowMs: 300000, - maxRequests: 5, - keyPrefix: 'mfa_verify', - enableProgressiveDelay: true, - blockOnExceed: true, - blockDurationMs: 1800000, - }) - @ApiOperation({ summary: 'Verify and complete MFA setup. Rate limit: 5 attempts per 5 minutes.' }) - @ApiResponse({ status: 200, description: 'MFA setup completed successfully.' }) - @ApiResponse({ status: 400, description: 'Invalid MFA token.' }) - @HttpCode(HttpStatus.OK) - async verifyMfa(@Req() req: Request, @Body('token') token: string) { - const user = req['user'] as any; - const verified = await this.mfaService.verifyMfaSetup(user.id, token); - - if (verified) { - // Generate backup codes after successful setup - const backupCodes = await this.mfaService.generateBackupCodes(user.id); - return { - message: 'MFA setup completed successfully', - backupCodes, - }; - } - - throw new Error('Invalid MFA token'); - } - - @Get('status') - @UseGuards(JwtAuthGuard) - @ApiOperation({ summary: 'Get MFA status for current user' }) - @ApiResponse({ status: 200, description: 'MFA status retrieved successfully.' }) - @HttpCode(HttpStatus.OK) - async getMfaStatus(@Req() req: Request) { - const user = req['user'] as any; - return this.mfaService.getMfaStatus(user.id); - } - - @Delete('disable') - @UseGuards(JwtAuthGuard, SensitiveEndpointRateLimitGuard) - @SensitiveRateLimit({ - windowMs: 3600000, - maxRequests: 3, - keyPrefix: 'mfa_disable', - enableProgressiveDelay: false, - blockOnExceed: false, - }) - @ApiOperation({ summary: 'Disable MFA for current user. Rate limit: 3 requests per hour.' }) - @ApiResponse({ status: 200, description: 'MFA disabled successfully.' }) - @HttpCode(HttpStatus.OK) - async disableMfa(@Req() req: Request) { - const user = req['user'] as any; - await this.mfaService.disableMfa(user.id); - return { message: 'MFA disabled successfully' }; - } - - @Post('backup-codes') - @UseGuards(JwtAuthGuard, SensitiveEndpointRateLimitGuard) - @SensitiveRateLimit({ - windowMs: 3600000, - maxRequests: 3, - keyPrefix: 'mfa_backup_gen', - enableProgressiveDelay: false, - blockOnExceed: false, - }) - @ApiOperation({ summary: 'Generate new backup codes. Rate limit: 3 requests per hour.' }) - @ApiResponse({ status: 200, description: 'Backup codes generated successfully.' }) - @HttpCode(HttpStatus.OK) - async generateBackupCodes(@Req() req: Request) { - const user = req['user'] as any; - const backupCodes = await this.mfaService.generateBackupCodes(user.id); - return { backupCodes }; - } - - @Post('verify-backup') - @UseGuards(JwtAuthGuard, SensitiveEndpointRateLimitGuard) - @SensitiveRateLimit({ - windowMs: 300000, - maxRequests: 10, - keyPrefix: 'mfa_backup_verify', - enableProgressiveDelay: true, - blockOnExceed: true, - blockDurationMs: 3600000, - }) - @ApiOperation({ summary: 'Verify backup code. Rate limit: 10 attempts per 5 minutes.' }) - @ApiResponse({ status: 200, description: 'Backup code verified successfully.' }) - @ApiResponse({ status: 401, description: 'Invalid backup code.' }) - @HttpCode(HttpStatus.OK) - async verifyBackupCode(@Req() req: Request, @Body('code') code: string) { - const user = req['user'] as any; - const verified = await this.mfaService.verifyBackupCode(user.id, code); - - if (!verified) { - throw new Error('Invalid backup code'); - } - - return { message: 'Backup code verified successfully' }; - } -} diff --git a/src/auth/mfa/mfa.module.ts b/src/auth/mfa/mfa.module.ts deleted file mode 100644 index fdf14606..00000000 --- a/src/auth/mfa/mfa.module.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Module } from '@nestjs/common'; -import { MfaService } from './mfa.service'; -import { MfaController } from './mfa.controller'; - -@Module({ - controllers: [MfaController], - providers: [MfaService], - exports: [MfaService], -}) -export class MfaModule {} diff --git a/src/auth/mfa/mfa.service.ts b/src/auth/mfa/mfa.service.ts deleted file mode 100644 index 83ece6b3..00000000 --- a/src/auth/mfa/mfa.service.ts +++ /dev/null @@ -1,150 +0,0 @@ -import { Injectable, UnauthorizedException, BadRequestException } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; -import { RedisService } from '../../common/services/redis.service'; -import { StructuredLoggerService } from '../../common/logging/logger.service'; -import * as speakeasy from 'speakeasy'; -import * as QRCode from 'qrcode'; - -@Injectable() -export class MfaService { - constructor( - private readonly configService: ConfigService, - private readonly redisService: RedisService, - private readonly logger: StructuredLoggerService, - ) { - this.logger.setContext('MfaService'); - } - - async generateMfaSecret(userId: string, email: string): Promise<{ secret: string; qrCode: string }> { - // Generate a new secret - const secret = speakeasy.generateSecret({ - name: `PropChain (${email})`, - issuer: 'PropChain', - }); - - // Generate QR code for authenticator apps - const qrCode = await QRCode.toDataURL(secret.otpauth_url); - - // Store the secret temporarily (will be confirmed during setup) - const expiry = this.configService.get('MFA_CODE_EXPIRY', 300); - await this.redisService.setex(`mfa_setup:${userId}`, expiry, secret.base32); - - this.logger.logAuth('MFA secret generated', { userId }); - - return { - secret: secret.base32, - qrCode, - }; - } - - async verifyMfaSetup(userId: string, token: string): Promise { - const secret = await this.redisService.get(`mfa_setup:${userId}`); - - if (!secret) { - throw new BadRequestException('MFA setup session expired or not found'); - } - - const verified = speakeasy.totp.verify({ - secret, - encoding: 'base32', - token, - window: 2, // Allow 2 time periods of tolerance - }); - - if (verified) { - // Store the confirmed secret - await this.redisService.set(`mfa_secret:${userId}`, secret); - await this.redisService.del(`mfa_setup:${userId}`); - this.logger.logAuth('MFA setup completed', { userId }); - } else { - this.logger.warn('MFA setup verification failed', { userId }); - } - - return verified; - } - - async verifyMfaToken(userId: string, token: string): Promise { - const secret = await this.redisService.get(`mfa_secret:${userId}`); - - if (!secret) { - throw new UnauthorizedException('MFA not enabled for this user'); - } - - const verified = speakeasy.totp.verify({ - secret, - encoding: 'base32', - token, - window: 2, - }); - - if (verified) { - // Store successful verification to prevent replay attacks - const expiry = this.configService.get('MFA_CODE_EXPIRY', 300); - await this.redisService.setex(`mfa_verified:${userId}:${token}`, expiry, '1'); - this.logger.logAuth('MFA token verified', { userId }); - } else { - this.logger.warn('MFA token verification failed', { userId }); - } - - return verified; - } - - async isMfaEnabled(userId: string): Promise { - const secret = await this.redisService.get(`mfa_secret:${userId}`); - return secret !== null; - } - - async disableMfa(userId: string): Promise { - await this.redisService.del(`mfa_secret:${userId}`); - await this.redisService.del(`mfa_backup_codes:${userId}`); - this.logger.logAuth('MFA disabled', { userId }); - } - - async generateBackupCodes(userId: string): Promise { - const codes = []; - for (let i = 0; i < 10; i++) { - // Generate 8-character backup codes - const code = Math.random().toString(36).substring(2, 10).toUpperCase(); - codes.push(code); - } - - // Store backup codes with hash for security - const expiry = this.configService.get('MFA_CODE_EXPIRY', 300) * 12; // 1 hour * 12 = 12 hours - await this.redisService.setex(`mfa_backup_codes:${userId}`, expiry, JSON.stringify(codes)); - - this.logger.logAuth('MFA backup codes generated', { userId }); - return codes; - } - - async verifyBackupCode(userId: string, code: string): Promise { - const codesData = await this.redisService.get(`mfa_backup_codes:${userId}`); - - if (!codesData) { - return false; - } - - const codes = JSON.parse(codesData); - const index = codes.indexOf(code.toUpperCase()); - - if (index !== -1) { - // Remove used code - codes.splice(index, 1); - await this.redisService.set(`mfa_backup_codes:${userId}`, JSON.stringify(codes)); - this.logger.logAuth('MFA backup code used', { userId }); - return true; - } - - return false; - } - - async getMfaStatus(userId: string): Promise<{ enabled: boolean; hasBackupCodes: boolean }> { - const enabled = await this.isMfaEnabled(userId); - const backupCodes = await this.redisService.get(`mfa_backup_codes:${userId}`); - const hasBackupCodes = backupCodes !== null && JSON.parse(backupCodes).length > 0; - - return { - enabled, - hasBackupCodes, - }; - } -} diff --git a/src/auth/middleware/auth.middleware.ts b/src/auth/middleware/auth.middleware.ts deleted file mode 100644 index 43f40d2d..00000000 --- a/src/auth/middleware/auth.middleware.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Injectable, NestMiddleware } from '@nestjs/common'; -import { Request, Response, NextFunction } from 'express'; -import { rateLimit } from 'express-rate-limit'; - -@Injectable() -export class AuthRateLimitMiddleware implements NestMiddleware { - use(req: Request, res: Response, next: NextFunction) { - // Apply rate limiting specifically to auth endpoints - if (req.path.includes('/auth')) { - const limiter = rateLimit({ - windowMs: 15 * 60 * 1000, // 15 minutes - max: 5, // Limit each IP to 5 requests per windowMs - message: 'Too many authentication attempts, please try again later.', - standardHeaders: true, - legacyHeaders: false, - }); - - return limiter(req, res, next); - } - - next(); - } -} diff --git a/src/auth/strategies/jwt.strategy.ts b/src/auth/strategies/jwt.strategy.ts deleted file mode 100644 index c01ef532..00000000 --- a/src/auth/strategies/jwt.strategy.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { ExtractJwt, Strategy } from 'passport-jwt'; -import { PassportStrategy } from '@nestjs/passport'; -import { Injectable, UnauthorizedException } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; -import { UserService } from '../../users/user.service'; -import { JWT_TOKEN_USE } from '../constants'; -import { JwtPayload } from '../auth.types'; - -@Injectable() -export class JwtStrategy extends PassportStrategy(Strategy) { - constructor( - private configService: ConfigService, - private userService: UserService, - ) { - super({ - jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), - ignoreExpiration: false, - secretOrKey: configService.get('JWT_SECRET'), - }); - } - - async validate(payload: JwtPayload) { - if (payload.tokenUse === JWT_TOKEN_USE.REFRESH) { - throw new UnauthorizedException(); - } - - const user = await this.userService.findById(payload.sub); - - if (!user) { - throw new UnauthorizedException(); - } - - const { password: _, ...safe } = user as Record & { password?: string }; - - return { - ...safe, - jti: payload.jti, - sid: payload.sid, - tokenUse: payload.tokenUse ?? JWT_TOKEN_USE.ACCESS, - }; - } -} diff --git a/src/auth/strategies/local.strategy.ts b/src/auth/strategies/local.strategy.ts deleted file mode 100644 index cde5c9e9..00000000 --- a/src/auth/strategies/local.strategy.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Strategy } from 'passport-local'; -import { PassportStrategy } from '@nestjs/passport'; -import { Injectable, UnauthorizedException } from '@nestjs/common'; -import { UserService } from '../../users/user.service'; -import * as bcrypt from 'bcrypt'; - -@Injectable() -export class LocalStrategy extends PassportStrategy(Strategy) { - constructor(private userService: UserService) { - super({ - usernameField: 'email', - }); - } - - async validate(email: string, password: string): Promise { - const user = (await this.userService.findByEmail(email)) as { password: string | null; [key: string]: any } | null; - - if (!user || !user.password) { - throw new UnauthorizedException('Invalid credentials'); - } - - const isPasswordValid = await bcrypt.compare(password, user.password as string); - - if (!isPasswordValid) { - throw new UnauthorizedException('Invalid credentials'); - } - - // Return user without password - const { password: _, ...result } = user; - return result; - } -} diff --git a/src/auth/strategies/web3.strategy.ts b/src/auth/strategies/web3.strategy.ts deleted file mode 100644 index 4bd39b9e..00000000 --- a/src/auth/strategies/web3.strategy.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { Strategy } from 'passport-custom'; -import { PassportStrategy } from '@nestjs/passport'; -import { Injectable, UnauthorizedException } from '@nestjs/common'; -import { ethers } from 'ethers'; -import { UserService } from '../../users/user.service'; - -@Injectable() -export class Web3Strategy extends PassportStrategy(Strategy, 'web3') { - constructor(private userService: UserService) { - super(); - } - - async validate(req: any) { - const { walletAddress, signature } = req.body; - - if (!walletAddress || !signature) { - throw new UnauthorizedException('Wallet address and signature are required'); - } - - // Verify the signature - const isValid = await this.verifySignature(walletAddress, signature); - if (!isValid) { - throw new UnauthorizedException('Invalid signature'); - } - - // Find or create user - let user = await this.userService.findByWalletAddress(walletAddress); - - if (!user) { - user = await this.userService.create({ - email: `${walletAddress}@wallet.auth`, - password: Math.random().toString(36).slice(-10), - walletAddress, - firstName: 'Web3', - lastName: 'User', - }); - } - - return user; - } - - private async verifySignature(walletAddress: string, signature: string): Promise { - try { - // NOTE: In production, use a nonce stored in Redis to prevent replay attacks - const message = 'Welcome to PropChain!\n\nClick to sign in and accept the Terms of Service.'; - - const recoveredAddress = ethers.verifyMessage(message, signature); - return recoveredAddress.toLowerCase() === walletAddress.toLowerCase(); - } catch (error) { - // For now, keeping as console.error but should be replaced with proper logger - // when the service is properly injected - console.error('Error verifying signature:', error); - return false; - } - } -} diff --git a/src/auth/wallet-signature.service.ts b/src/auth/wallet-signature.service.ts deleted file mode 100644 index a90b9015..00000000 --- a/src/auth/wallet-signature.service.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { Injectable, Logger, UnauthorizedException } from '@nestjs/common'; -import { Request } from 'express'; -import * as StellarSdk from 'stellar-sdk'; - -/** - * Wallet Signature Verification Service - * - * Handles verification of Stellar wallet signatures to authenticate users. - * This service addresses issue #270 by ensuring that wallet address ownership - * is verified before allowing sensitive operations like email updates. - */ -@Injectable() -export class WalletSignatureService { - private readonly logger = new Logger(WalletSignatureService.name); - - /** - * Verify Stellar wallet signature - * - * @param signature - The signature from x-signature header - * @param walletAddress - The wallet address claiming ownership - * @param message - The message that was signed (default: "Login to SoroSusu") - * @returns {boolean} True if signature is valid - * @throws {UnauthorizedException} If signature is invalid - */ - verifySignature(signature: string, walletAddress: string, message: string = 'Login to SoroSusu'): boolean { - try { - if (!signature) { - throw new UnauthorizedException('Signature is required'); - } - - if (!walletAddress) { - throw new UnauthorizedException('Wallet address is required'); - } - - // Create a keypair from the wallet address - const keypair = StellarSdk.Keypair.fromPublicKey(walletAddress); - - // Verify the signature - const isValid = keypair.verify(message, signature); - - if (!isValid) { - this.logger.warn(`Invalid signature for wallet ${walletAddress}`); - throw new UnauthorizedException('Invalid signature'); - } - - this.logger.log(`Signature verified successfully for wallet ${walletAddress}`); - return true; - } catch (error) { - if (error instanceof UnauthorizedException) { - throw error; - } - - this.logger.error('Signature verification failed', error); - throw new UnauthorizedException('Signature verification failed'); - } - } - - /** - * Extract signature from request headers - * - * @param request - Express request object - * @returns {string} The signature from x-signature header - * @throws {UnauthorizedException} If signature header is missing - */ - extractSignature(request: Request): string { - const signature = request.headers['x-signature'] as string; - - if (!signature) { - this.logger.warn('Missing x-signature header in request'); - throw new UnauthorizedException('x-signature header is required'); - } - - return signature; - } - - /** - * Verify wallet ownership for user update operations - * - * @param request - Express request object - * @param userWalletAddress - The user's stored wallet address - * @returns {boolean} True if ownership is verified - * @throws {UnauthorizedException} If ownership cannot be verified - */ - verifyWalletOwnership(request: Request, userWalletAddress: string): boolean { - try { - const signature = this.extractSignature(request); - - if (!userWalletAddress) { - throw new UnauthorizedException('User does not have a wallet address'); - } - - return this.verifySignature(signature, userWalletAddress); - } catch (error) { - this.logger.error('Wallet ownership verification failed', error); - throw error; - } - } - - /** - * Generate message for signing - * - * @param customMessage - Optional custom message - * @returns {string} Message to be signed by user - */ - generateSigningMessage(customMessage?: string): string { - return customMessage || 'Login to SoroSusu'; - } - - /** - * Validate Stellar address format - * - * @param address - The Stellar address to validate - * @returns {boolean} True if address is valid - */ - isValidStellarAddress(address: string): boolean { - try { - StellarSdk.StrKey.decodeEd25519PublicKey(address); - return true; - } catch (error) { - return false; - } - } -} diff --git a/src/backup-recovery/DISASTER_RECOVERY_RUNBOOK.md b/src/backup-recovery/DISASTER_RECOVERY_RUNBOOK.md deleted file mode 100644 index f78bb573..00000000 --- a/src/backup-recovery/DISASTER_RECOVERY_RUNBOOK.md +++ /dev/null @@ -1,589 +0,0 @@ -# Backup and Disaster Recovery System - Operational Runbooks - -## Table of Contents - -1. [Database Backup Operations](#database-backup-operations) -2. [Document Backup Operations](#document-backup-operations) -3. [Disaster Recovery Procedures](#disaster-recovery-procedures) -4. [Emergency Recovery Steps](#emergency-recovery-steps) -5. [Monitoring and Alerting](#monitoring-and-alerting) -6. [Incident Response](#incident-response) - ---- - -## Database Backup Operations - -### 1. Manual Full Database Backup - -**Purpose**: Create a complete point-in-time snapshot of the production database - -**Procedure**: - -```bash -# Using API -curl -X POST http://localhost:3000/v1/backup-recovery/database/backup/full \ - -H "Authorization: Bearer " \ - -H "Content-Type: application/json" \ - -d '{ - "tags": { - "type": "manual", - "reason": "pre-deployment", - "operator": "admin@propchain.local" - } - }' - -# Using CLI -npm run db:backup -``` - -**Expected Outcome**: -- HTTP Status: 202 (Accepted) -- Response includes backup ID, timestamp, and estimated duration -- Backup process runs asynchronously in background -- Monitor progress via `/backup-recovery/database/backups/:backupId` - -**Troubleshooting**: -- If backup times out (>30 minutes), check database locks: `SELECT * FROM pg_locks;` -- If storage space insufficient, run retention policies: `POST /backup-recovery/retention/enforce-policies` - ---- - -### 2. Verify Database Backup Integrity - -**Purpose**: Ensure backup is restorable and not corrupted - -**Procedure**: - -```bash -# Trigger verification -curl -X POST http://localhost:3000/v1/backup-recovery/verification/verify/:backupId \ - -H "Authorization: Bearer " - -# Get verification results -curl -X GET http://localhost:3000/v1/backup-recovery/verification/:backupId \ - -H "Authorization: Bearer " -``` - -**Expected Results**: -- Checksum verification: PASSED -- File accessibility: Accessible -- Restorability test: Restorable -- Duration: <5 minutes - -**If Verification Fails**: -1. Check backup file exists: `ls -lh backups/database/full/:backupId.dump` -2. Check file permissions: `stat backups/database/full/:backupId.dump` -3. Test database connectivity -4. Recreate backup if corrupted - ---- - -### 3. Point-in-Time Recovery (PITR) - -**Purpose**: Restore database to a specific point in time - -**Procedure**: - -```bash -# Step 1: Get PITR information for target timestamp -curl -X GET "http://localhost:3000/v1/backup-recovery/recovery/point-in-time/2024-01-15T14:30:00Z" \ - -H "Authorization: Bearer " - -# Step 2: Initiate PITR -curl -X POST http://localhost:3000/v1/backup-recovery/disaster-recovery/point-in-time-recovery \ - -H "Authorization: Bearer " \ - -H "Content-Type: application/json" \ - -d '{ - "targetTimestamp": "2024-01-15T14:30:00Z", - "backupId": "full_1705329600000_abc123", - "targetEnvironment": "staging" - }' - -# Step 3: Monitor recovery progress -curl -X GET http://localhost:3000/v1/backup-recovery/disaster-recovery/status \ - -H "Authorization: Bearer " -``` - -**Expected Duration**: 20-45 minutes (depending on database size) - -**Validation**: -- Check record counts match expected values -- Query known data points -- Verify application can connect -- Test critical business flows - -**Rollback**: -- If recovery fails, promote previous replica -- Issue: `POST /backup-recovery/disaster-recovery/failover` to alternate region - ---- - -### 4. Backup Retention Policy - -**Policy**: -- Daily full backups: Retain 30 days -- Incremental backups: Retain 7 days -- Weekly point-in-time: Retain 12 weeks -- Monthly snapshots: Retain 12 months -- Archived backups: Retain 7 years (cold storage) - -**Automatic Enforcement**: -- Runs daily at 01:00 UTC -- Old backups automatically deleted -- Expired backups moved to archive storage - -**Manual Enforcement**: - -```bash -curl -X POST http://localhost:3000/v1/backup-recovery/retention/enforce-policies \ - -H "Authorization: Bearer " -``` - ---- - -## Document Backup Operations - -### 1. Manual Document Backup - -**Purpose**: Backup all user-uploaded documents - -**Procedure**: - -```bash -curl -X POST http://localhost:3000/v1/backup-recovery/documents/backup \ - -H "Authorization: Bearer " \ - -H "Content-Type: application/json" \ - -d '{ - "tags": { - "type": "manual", - "reason": "audit" - } - }' -``` - -**Locations Replicated To**: -- Local storage: `backups/documents/snapshots/` -- Azure Blob Storage: `document-backups/2024/01/` -- AWS S3: `s3://propchain-backups/document-backups/2024/01/` - ---- - -### 2. Verify Document Backup - -**Purpose**: Ensure all documents are properly backed up - -**Procedure**: - -```bash -# Trigger verification -curl -X POST http://localhost:3000/v1/backup-recovery/documents/backups/:backupId/verify \ - -H "Authorization: Bearer " - -# Get statistics -curl -X GET http://localhost:3000/v1/backup-recovery/documents/statistics \ - -H "Authorization: Bearer " -``` - -**Verification Checks**: -- Archive integrity -- Manifest validity -- File checksums -- All data accessible - ---- - -### 3. Restore Document from Backup - -**Procedure**: - -```bash -# 1. Extract backup archive -tar -xzf backups/documents/snapshots/docs_1705329600000_abc123.tar.gz - -# 2. Verify manifest -cat backups/documents/snapshots/docs_1705329600000_abc123/MANIFEST.json - -# 3. Restore specific document -cp -r docs_backup/document_id/* uploads/documents/document_id/ - -# 4. Verify restoration -curl -X GET http://localhost:3000/v1/documents/document_id \ - -H "Authorization: Bearer " -``` - ---- - -## Disaster Recovery Procedures - -### 1. Create Disaster Recovery Plan - -**Purpose**: Define recovery strategy for critical failures - -**Procedure**: - -```bash -curl -X POST http://localhost:3000/v1/backup-recovery/disaster-recovery/plans \ - -H "Authorization: Bearer " \ - -H "Content-Type: application/json" \ - -d '{ - "id": "production_dr_plan", - "name": "Production Disaster Recovery Plan", - "rpo": "1h", - "rto": "4h", - "failoverRegions": ["us-east-1", "eu-west-1"], - "healthCheckInterval": 300000, - "automaticFailover": false, - "notificationChannels": ["slack", "email"], - "testInterval": 604800000 - }' -``` - -**Parameters**: -- **RPO** (Recovery Point Objective): Maximum acceptable data loss (1 hour = max 1 hour of data loss) -- **RTO** (Recovery Time Objective): Maximum acceptable downtime (4 hours) -- **failoverRegions**: Ordered list of fallback regions -- **automaticFailover**: Enable automated failover (false = manual only) - ---- - -### 2. Automated DR Testing - -**Purpose**: Validate recovery procedures without impacting production - -**Procedure**: - -```bash -# Trigger manual DR test -curl -X POST http://localhost:3000/v1/backup-recovery/disaster-recovery/test/production_dr_plan \ - -H "Authorization: Bearer " - -# Monitor test progress -curl -X GET http://localhost:3000/v1/backup-recovery/disaster-recovery/status \ - -H "Authorization: Bearer " -``` - -**Test Steps**: -1. Create isolated test environment -2. Restore latest production backup -3. Run application smoke tests -4. Validate data consistency -5. Cleanup test environment - -**Expected Duration**: 30-60 minutes - -**Review Results**: -```bash -curl -X GET http://localhost:3000/v1/backup-recovery/verification/lifecycle-stats \ - -H "Authorization: Bearer " -``` - ---- - -### 3. Manual Failover to Alternate Region - -**Purpose**: Redirect traffic to standby region during primary region failure - -**Prerequisites**: -- Verify DR plan exists and is active -- Confirm target region has current replica -- Notify stakeholders - -**Procedure**: - -```bash -# Step 1: Initiate failover -curl -X POST http://localhost:3000/v1/backup-recovery/disaster-recovery/failover \ - -H "Authorization: Bearer " \ - -H "Content-Type: application/json" \ - -d '{ - "planId": "production_dr_plan", - "targetRegion": "us-east-1" - }' - -# Response: -# { -# "status": "INITIATED", -# "failoverStartTime": "2024-01-15T10:00:00Z", -# "estimatedCompletionTime": "2024-01-15T10:30:00Z" -# } - -# Step 2: Monitor failover progress -curl -X GET http://localhost:3000/v1/backup-recovery/disaster-recovery/status \ - -H "Authorization: Bearer " -``` - -**Failover Sequence**: -1. ✅ Notify stakeholders via all channels -2. ✅ Prepare target infrastructure -3. ✅ Promote read replica to primary -4. ✅ Update DNS records (TTL: 60 seconds) -5. ✅ Validate application connectivity -6. ✅ Monitor health checks -7. ✅ Confirm failover success - -**Expected Duration**: 10-15 minutes - -**Post-Failover**: -- Monitor application metrics for 30 minutes -- Verify all integrations are working -- Update status page -- Begin primary region investigation - ---- - -## Emergency Recovery Steps - -### Scenario 1: Complete Database Failure (Primary Region) - -**Symptoms**: -- Database connection errors from all applications -- Health checks failing -- No backups in primary region - -**Recovery Steps**: - -```bash -# Step 1: Assess situation -curl -X GET http://localhost:3000/v1/backup-recovery/disaster-recovery/status - -# Step 2: Verify backup availability in alternate regions -curl -X GET http://localhost:3000/v1/backup-recovery/database/backups?status=VERIFIED - -# Step 3: Initiate failover -curl -X POST http://localhost:3000/v1/backup-recovery/disaster-recovery/failover \ - -H "Authorization: Bearer " \ - -d '{"planId": "production_dr_plan", "targetRegion": "eu-west-1"}' - -# Step 4: Monitor restoration -curl -X GET http://localhost:3000/v1/backup-recovery/disaster-recovery/status - -# Step 5: Investigate primary region -# - Check RDS status in AWS console -# - Review CloudWatch logs -# - Check storage capacity -# - Verify network connectivity -``` - -**RTO: 15-30 minutes** - ---- - -### Scenario 2: Data Corruption or Ransomware - -**Symptoms**: -- Unusual data modifications -- Large-scale deletions -- Unknown encryption applied - -**Recovery Steps**: - -```bash -# Step 1: IMMEDIATELY isolate affected systems -# - Stop replication -# - Block database access except for recovery team -# - Capture forensics from affected nodes - -# Step 2: Find last known-good backup -curl -X GET http://localhost:3000/v1/backup-recovery/recovery/point-in-time/$(date -d '1 hour ago' --rfc-3339=seconds) \ - -H "Authorization: Bearer " - -# Step 3: Perform point-in-time recovery to staging -curl -X POST http://localhost:3000/v1/backup-recovery/disaster-recovery/point-in-time-recovery \ - -H "Authorization: Bearer " \ - -d '{ - "targetTimestamp": "2024-01-15T09:00:00Z", - "backupId": "full_1705329600000_abc123", - "targetEnvironment": "forensics" - }' - -# Step 4: Validate recovered data -# - Sample data queries -# - Application connectivity -# - No corruption indicators - -# Step 5: If validated, promote to production -# - DNS update -# - Monitor -# - Communication with users - -# Step 6: Forensic analysis -# - Review audit logs -# - Identify attack vector -# - Update security policies -``` - -**RTO: 1-2 hours** - ---- - -### Scenario 3: Document Storage Failure - -**Symptoms**: -- Document download failures -- Storage replication errors -- High latency - -**Recovery Steps**: - -```bash -# Step 1: Check backup status -curl -X GET http://localhost:3000/v1/backup-recovery/documents/statistics - -# Step 2: Identify affected documents -curl -X GET http://localhost:3000/v1/documents?status=failed - -# Step 3: Restore from latest backup -# Extract backup archive and restore missing documents -tar -xzf backups/documents/snapshots/docs_latest.tar.gz -cp -r docs_backup/* uploads/documents/ - -# Step 4: Verify restoration -curl -X GET http://localhost:3000/v1/backup-recovery/documents/backups/:backupId/verify - -# Step 5: Resume normal operations -``` - -**RTO: 30 minutes** - ---- - -## Monitoring and Alerting - -### 1. Critical Alerts - -**Alert**: Backup Failed (CRITICAL) -- **Action**: Immediate investigation required -- **Steps**: - ```bash - curl -X GET http://localhost:3000/v1/backup-recovery/monitoring/alerts?severity=CRITICAL - ``` - -**Alert**: Backup Timeout (CRITICAL) -- **Action**: Kill backup process, investigate database locks, restart backup - -**Alert**: Storage Full (CRITICAL) -- **Action**: Run retention policies immediately or expand storage - ---- - -### 2. Monitoring Dashboard - -Access operational metrics: - -```bash -curl -X GET http://localhost:3000/v1/backup-recovery/monitoring/dashboard \ - -H "Authorization: Bearer " - -# Response includes: -# { -# "alerts": { "critical": 0, "high": 1, "total": 2 }, -# "recentBackups": [...] -# "systemHealth": { "status": "HEALTHY" } -# } -``` - ---- - -### 3. Alert Management - -```bash -# Acknowledge alert -curl -X POST http://localhost:3000/v1/backup-recovery/monitoring/alerts/:alertId/acknowledge \ - -H "Authorization: Bearer " \ - -d '{"acknowledgedBy": "admin@propchain.local"}' - -# Resolve alert -curl -X POST http://localhost:3000/v1/backup-recovery/monitoring/alerts/:alertId/resolve \ - -H "Authorization: Bearer " -``` - ---- - -## Incident Response - -### Incident Severity Levels - -| Level | Response Time | Escalation | -|-------|--------------|------------| -| P1 - Critical | 15 minutes | VP Engineering + DevOps | -| P2 - High | 30 minutes | Engineering Lead + DevOps | -| P3 - Medium | 1 hour | DevOps Team | -| P4 - Low | 4 hours | DevOps Team | - ---- - -### Incident Communication Template - -``` -Subject: [INCIDENT] Backup System - - -SEVERITY: P<1-4> -START_TIME: -IMPACT: -ESTIMATED_RECOVERY: